APM 数据集

Microsoft.SystemCenter.DataWarehouse.DataSet.APM (DataWarehouseDataSet)

定义 APM 的存储和聚合

Element properties:

AccessibilityInternal

Source Code:

<DataWarehouseDataSet ID="Microsoft.SystemCenter.DataWarehouse.DataSet.APM" Accessibility="Internal">
<Dependencies/>
<Configuration/>
<Install>IF (OBJECTPROPERTY(OBJECT_ID('APM.PMTRACE'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.PMTRACE (
PMTRACEID INT IDENTITY(1,1) NOT NULL,
UTCDATE DATETIME NOT NULL,
DATA NVARCHAR(MAX) NULL,
PMSTATUS tinyint NULL
CONSTRAINT PK_PMTRACE PRIMARY KEY (PMTRACEID)
)
END
GO

IF NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'PMTRACE' AND TABLE_SCHEMA = N'apm' AND COLUMN_NAME = 'UTCDATE' AND COLUMN_DEFAULT IS NOT NULL)
BEGIN
ALTER TABLE APM.PMTRACE ADD CONSTRAINT DF_PMTRACE_UTCDATE DEFAULT GETUTCDATE() FOR UTCDATE;
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.PMSERVEREVENTTRACE'), 'IsTable') IS NULL)
BEGIN
/* server event trace table */
CREATE TABLE APM.PMSERVEREVENTTRACE (
EVENTID BIGINT NOT NULL,
PMTRACEID INT NOT NULL
)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PMSERVEREVENTTRACE]') AND name = N'IDX_EVENTID'
)
BEGIN
CREATE INDEX IDX_EVENTID ON APM.PMSERVEREVENTTRACE
(
EVENTID
)
INCLUDE(PMTRACEID)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PMSERVEREVENTTRACE]') AND name = N'IX_PMSERVEREVENTTRACE_PMTRACEID'
)
BEGIN
CREATE INDEX IX_PMSERVEREVENTTRACE_PMTRACEID ON APM.PMSERVEREVENTTRACE
(PMTRACEID)
END
GO

EXEC DomainTableRegisterIndexOptimization
@TableName = 'PMSERVEREVENTTRACE'
,@SchemaName = 'APM'
,@DatasetId = '$Config/DatasetId$'
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.ADT_PMSERVEREVENTTRACE'), 'IsTrigger') IS NULL)
BEGIN
exec(
'CREATE TRIGGER APM.ADT_PMSERVEREVENTTRACE ON APM.PMSERVEREVENTTRACE AFTER DELETE
AS
BEGIN
RETURN;
END')
END
GO

ALTER TRIGGER APM.ADT_PMSERVEREVENTTRACE ON APM.PMSERVEREVENTTRACE AFTER DELETE
AS
BEGIN
SET NOCOUNT ON
DELETE a FROM
APM.PMTRACE a JOIN deleted b ON a.PMTRACEID=b.PMTRACEID
WHERE NOT EXISTS (SELECT 1 FROM APM.PMSERVEREVENTTRACE WHERE PMTRACEID=a.PMTRACEID)
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.PMCLIENTEVENTTRACE'), 'IsTable') IS NULL)
BEGIN
/* client event trace table */
CREATE TABLE APM.PMCLIENTEVENTTRACE (
CSEVENTID INT NOT NULL,
PMTRACEID INT NOT NULL
)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PMCLIENTEVENTTRACE]') AND name = N'IDX_EVENTID'
)
BEGIN
CREATE INDEX IDX_EVENTID ON APM.PMCLIENTEVENTTRACE
(CSEVENTID)
INCLUDE(PMTRACEID)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PMCLIENTEVENTTRACE]') AND name = N'IX_PMCLIENTEVENTTRACE_PMTRACEID'
)
BEGIN
CREATE INDEX IX_PMCLIENTEVENTTRACE_PMTRACEID ON APM.PMCLIENTEVENTTRACE
(PMTRACEID)
END
GO

EXEC DomainTableRegisterIndexOptimization
@TableName = 'PMCLIENTEVENTTRACE'
,@SchemaName = 'APM'
,@DatasetId = '$Config/DatasetId$'
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.ADT_PMCLIENTEVENTTRACE'), 'IsTrigger') IS NULL)
BEGIN
EXEC('
CREATE TRIGGER APM.ADT_PMCLIENTEVENTTRACE ON APM.PMCLIENTEVENTTRACE
AFTER DELETE
AS
BEGIN
RETURN;
END')
END
GO

ALTER TRIGGER APM.ADT_PMCLIENTEVENTTRACE ON APM.PMCLIENTEVENTTRACE
AFTER DELETE
AS
BEGIN
SET NOCOUNT ON

DELETE a FROM
APM.PMTRACE a JOIN deleted b ON a.PMTRACEID=b.PMTRACEID
WHERE NOT EXISTS (SELECT 1 FROM APM.PMCLIENTEVENTTRACE WHERE PMTRACEID=a.PMTRACEID)
END
go

IF (OBJECTPROPERTY(OBJECT_ID('APM.PMENTITYMAPPING'), 'IsTable') IS NULL)
BEGIN
/*==============================================================*/
/* Table: PMENTITYMAPPING */
/*==============================================================*/
CREATE TABLE APM.PMENTITYMAPPING (
PMENTITYMAPPINGID INT IDENTITY,
ALIAS NVARCHAR(50) NOT NULL,
ENTITY NVARCHAR(50) NOT NULL,
FIELD NVARCHAR(50) NULL,
FIELDTYPE NVARCHAR(50) NULL,
ISPROCEDURE BIT NOT NULL,
ISCLIENT BIT NOT NULL,
CONSTRAINT PK_PMENTITYMAPPING PRIMARY KEY (PMENTITYMAPPINGID)
)

------------------ SERVER EVENT MAPING ------------------------
INSERT APM.PMENTITYMAPPING
(
ALIAS,
ENTITY,
FIELD,
FIELDTYPE ,
ISPROCEDURE,
ISCLIENT
)
SELECT N'EVENT.EVENTCLASSTYPE',N'V_PM_EVENT',N'EVENTCLASSTYPE',N'nvarchar(50)',0,0
UNION ALL
SELECT N'EVENT.SOURCE',N'V_PM_EVENT',N'SOURCE',N'nvarchar(255)',0,0
UNION ALL
SELECT N'EVENT.MACHINENAME',N'V_PM_EVENT',N'MACHINENAME',N'nvarchar(255)',0,0
UNION ALL
SELECT N'EVENT.ROOTNODENAME',N'V_PM_EVENT',N'ROOTNODENAME',N'nvarchar(255)',0,0
UNION ALL
SELECT N'EVENT.DESCRIPTION',N'V_PM_EVENT',N'DESCRIPTION',N'nvarchar(255)',0,0
UNION ALL
SELECT N'EVENT.USERNAME',N'V_PM_EVENT',N'USERNAME',N'nvarchar(255)',0,0
UNION ALL
SELECT N'EVENT.EXCEPTIONCLASS',N'V_PM_EVENT',N'EXCEPTIONCLASS',N'nvarchar(255)',0,0
UNION ALL
SELECT N'EVENT.EVENTDURATION',N'V_PM_EVENT',N'EVENTDURATION',N'decimal(35,0)',0,0
UNION ALL
SELECT N'EVENT.EVENTGROUPID',N'V_PM_EVENT',N'SEVIEWEREGID',N'int',0,0
UNION ALL
SELECT N'EVENT.HEAVYLIGHT',N'V_PM_EVENT',N'HEAVYLIGHT',N'int',0,0
UNION ALL
SELECT N'EVENT.ASPECT',N'V_PM_EVENT',N'ASPECT',N'nvarchar(50)',0,0
UNION ALL
SELECT N'EVENT.PMSTATUS',N'EVENT',N'PMSTATUS',N'tinyint',0,0
UNION ALL
SELECT N'EVENT.HEAVIESTEXTERNALRESOURCE',N'V_PM_RESOURCE',N'RESOURCEMETHOD',N'nvarchar(255)',0,0
UNION ALL
SELECT N'EVENT.COMPONENT',N'V_PM_EVENTDETAIL',N'VALUE',N'COMPONENT',0,0
UNION ALL
SELECT N'EVENT.EVENTID',N'EVENT',N'EVENTID',N'int',0,0
UNION ALL
SELECT N'EVENT.CATEGORY',N'V_PM_EVENT',N'CATEGORY',N'nvarchar(50)',0,0
UNION ALL
SELECT N'EVENT.HEAVIESTNODE',N'V_PM_HEAVIESTNODE',N'VAL',N'nvarchar(255)',0,0
UNION ALL
SELECT N'EVENT.ROOTFUNCTION',N'V_PM_EVENTDETAIL',N'VALUE',N'ROOTFUNCTION',0,0
UNION ALL
SELECT N'EVENT.SLOWCALLDURATION',N'V_PM_HEAVIESTNODE',N'SELFDURATION',N'decimal(35,0)',0,0

------------------ CLIENT EVENT MAPING ------------------------
INSERT APM.PMENTITYMAPPING
(
ALIAS,
ENTITY,
FIELD,
FIELDTYPE ,
ISPROCEDURE,
ISCLIENT
)
SELECT N'EVENT.EVENTCLASSTYPE',N'V_PM_CSEVENT',N'EVENTCLASSTYPE',N'nvarchar(50)',0,1
UNION ALL
SELECT N'EVENT.SOURCE',N'V_PM_CSEVENT',N'SOURCE',N'nvarchar(255)',0,1
UNION ALL
SELECT N'EVENT.MACHINENAME',N'V_PM_CSEVENT',N'MACHINENAME',N'nvarchar(255)',0,1
UNION ALL
SELECT N'EVENT.ROOTNODENAME',N'V_PM_CSEVENTDETAIL',N'VALUE',N'ROOTNODENAME',0,1
UNION ALL
SELECT N'EVENT.DESCRIPTION',N'V_PM_CSEVENT',N'DESCRIPTION',N'nvarchar(255)',0,1
UNION ALL
SELECT N'EVENT.USERNAME',N'V_PM_CSEVENT',N'USERNAME',N'nvarchar(255)',0,1
UNION ALL
SELECT N'EVENT.EXCEPTIONCLASS',N'V_PM_CSEVENT',N'EXCEPTIONCLASS',N'nvarchar(255)',0,1
UNION ALL
SELECT N'EVENT.EVENTDURATION',N'V_PM_CSEVENT',N'EVENTDURATION',N'decimal(35,0)',0,1
UNION ALL
SELECT N'EVENT.EVENTGROUPID',N'V_PM_CSEVENT',N'SEVIEWEREGID',N'int',0,1
UNION ALL
SELECT N'EVENT.HEAVYLIGHT',N'V_PM_CSEVENT',N'HEAVYLIGHT',N'int',0,1
UNION ALL
SELECT N'EVENT.ASPECT',N'V_PM_CSEVENT',N'ASPECT',N'nvarchar(50)',0,1
UNION ALL
SELECT N'EVENT.PMSTATUS',N'V_PM_CSEVENTSTATUS',N'PMSTATUS',N'tinyint',0,1
UNION ALL
SELECT N'EVENT.HEAVIESTEXTERNALRESOURCE',N'V_PM_EMPTY',N'VAL',N'nvarchar(255)',0,1
UNION ALL
SELECT N'EVENT.COMPONENT',N'V_PM_CSEVENT',N'COMPONENT',N'nvarchar(50)',0,1
UNION ALL
SELECT N'EVENT.EVENTID',N'V_PM_CSEVENTSTATUS',N'EVENTID',N'int',0,1
UNION ALL
SELECT N'EVENT.CATEGORY',N'V_PM_CSEVENTDETAIL',N'VALUE',N'CATEGORY',0,1
UNION ALL
SELECT N'EVENT.HEAVIESTNODE',N'V_PM_CSHEAVIESTNODE',N'VAL',N'nvarchar(255)',0,1
UNION ALL
SELECT N'EVENT.ROOTFUNCTION',N'V_PM_CSEVENTDETAIL',N'VALUE',N'ROOTFUNCTION',0,1
UNION ALL
SELECT N'EVENT.SLOWCALLDURATION',N'V_PM_CSHEAVIESTNODE',N'SELFDURATION',N'decimal(35,0)',0,1
END
GO

IF NOT EXISTS
(
SELECT * FROM INFORMATION_SCHEMA.table_constraints WHERE TABLE_NAME = N'PMENTITYMAPPING' AND TABLE_SCHEMA = N'apm' AND CONSTRAINT_NAME=N'PMENTITYMAPPING_UNIQUE'
)
BEGIN
ALTER TABLE APM.PMENTITYMAPPING ADD CONSTRAINT PMENTITYMAPPING_UNIQUE
UNIQUE(ALIAS, ISCLIENT)
END
GO

/*==============================================================*/
/* Table: PMEVENTSTATUS */
/*==============================================================*/

IF (OBJECTPROPERTY(OBJECT_ID('APM.PMEVENTSTATUS'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.PMEVENTSTATUS (
PMSTATUSID int not null,
PMSTATUSNAME nvarchar(50) not null,
ISDEFAULT bit not null
)

INSERT INTO [APM].[PMEVENTSTATUS] ([PMSTATUSID], [PMSTATUSNAME], [ISDEFAULT])
SELECT 0, N'New', 1
UNION
SELECT 1, N'Reviewed', 1
UNION
SELECT 2, N'Deleted', 0
UNION
SELECT 3, N'By Design', 0
END
GO

IF NOT EXISTS (
SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'PMEVENTSTATUS' AND TABLE_SCHEMA = N'apm' AND COLUMN_NAME = 'ISDEFAULT' AND COLUMN_DEFAULT IS NOT NULL
)
BEGIN
ALTER TABLE APM.PMEVENTSTATUS ADD CONSTRAINT DF_PMEVENTSTATUS_ISDEFAULT DEFAULT 0 FOR ISDEFAULT
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.HourlyTable'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.HourlyTable (value datetime)
END
GO

/*==============================================================*/
/* Table: AGGREGATIONTYPE */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.AGGREGATIONTYPE'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.AGGREGATIONTYPE (
AGGREGATIONTYPEID int not null,
AGGREGATIONTYPEDEFAULTNAME nvarchar(50) not null,
AGGREGATIONINTERVALDURATIONMINUTES int not null,
AGGREGATIONSTARTDELAYMINUTES int not null,
constraint PK_AGGREGATIONTYPE primary key (AGGREGATIONTYPEID)
)

INSERT INTO APM.AGGREGATIONTYPE (
AGGREGATIONTYPEID,
AGGREGATIONTYPEDEFAULTNAME,
AGGREGATIONINTERVALDURATIONMINUTES,
AGGREGATIONSTARTDELAYMINUTES
)
values(
20,
'Hourly',
60,
5
)

INSERT INTO APM.AGGREGATIONTYPE (
AGGREGATIONTYPEID,
AGGREGATIONTYPEDEFAULTNAME,
AGGREGATIONINTERVALDURATIONMINUTES,
AGGREGATIONSTARTDELAYMINUTES
)
VALUES(
30,
'Daily',
1440,
20
)
END
GO

/*==============================================================*/
/* Table: APPLICATION */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.APPLICATION'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.APPLICATION (
APPLICATIONID int identity,
APPLICATION nvarchar(255) null,
TYPE int not null,
constraint PK_APPLICATION primary key (APPLICATIONID)
)
END
GO

/*==============================================================*/
/* Index: IX_APPLICATION */
/*==============================================================*/
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[APPLICATION]') AND name = N'IX_APPLICATION'
)
BEGIN
create unique index IX_APPLICATION on APM.APPLICATION (
APPLICATION ASC
)
END
GO

/*==============================================================*/
/* Table: APPLICATIONSOURCEMACHINE */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.APPLICATIONSOURCEMACHINE'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.APPLICATIONSOURCEMACHINE (
APPLICATIONSOURCEID int identity,
APPLICATIONID int null,
SOURCEID int null,
MACHINEID int null,
constraint PK_APPLICATIONSOURCEMACHINE primary key (APPLICATIONSOURCEID)
)
END
GO

/*==============================================================*/
/* Index: FK_SOURCE */
/*==============================================================*/
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[APPLICATIONSOURCEMACHINE]') AND name = N'FK_SOURCE'
)
BEGIN
create index FK_SOURCE on APM.APPLICATIONSOURCEMACHINE
(
SOURCEID ASC
)
INCLUDE ( [APPLICATIONID]) WITH (SORT_IN_TEMPDB = ON) ON [PRIMARY]
END
GO

/*==============================================================*/
/* Index: FK_APPLICATION */
/*==============================================================*/
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[APPLICATIONSOURCEMACHINE]') AND name = N'FK_APPLICATION'
)
BEGIN
create index FK_APPLICATION on APM.APPLICATIONSOURCEMACHINE (
APPLICATIONID ASC
)
END
GO

/*==============================================================*/
/* Index: FK_MACHINE */
/*==============================================================*/
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[APPLICATIONSOURCEMACHINE]') AND name = N'FK_MACHINE'
)
BEGIN
create index FK_MACHINE on APM.APPLICATIONSOURCEMACHINE (
MACHINEID ASC
)
INCLUDE ([APPLICATIONID])
END
GO

/*==============================================================*/
/* Table: ASPECT */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.ASPECT'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.ASPECT (
ASPECT nvarchar(50) null,
DESCRIPTION nvarchar(255) null,
ASPECTID int identity,
constraint PK_ASPECT primary key (ASPECTID)
)
END
GO

/*==============================================================*/
/* Index: IX_ASPECT */
/*==============================================================*/
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[ASPECT]') AND name = N'IX_ASPECT'
)
BEGIN
create unique index IX_ASPECT on APM.ASPECT (
ASPECT ASC
)
END
GO

/*==============================================================*/
/* Table: CONFIG */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.CONFIG'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.CONFIG (
CONFIGID int identity,
CONFIGNAME nvarchar(50) not null,
CONFIGVALUE ntext null,
constraint PK_CONFIG primary key (CONFIGID)
)

INSERT INTO APM.CONFIG (configname, configvalue) VALUES ('SECURITYMODE', '0')
INSERT INTO APM.CONFIG (CONFIGNAME, CONFIGVALUE) VALUES ('DATABASE_VERSION', '5.7')
INSERT INTO APM.CONFIG (CONFIGNAME, CONFIGVALUE) VALUES ('DATABASE_NAME', 'Reporting')
INSERT INTO APM.CONFIG (CONFIGNAME, CONFIGVALUE) VALUES ('SCHEMA_VERSION', '1')

/*Lifetime for events with "Deleted" status (hours)*/
INSERT INTO APM.CONFIG (CONFIGNAME, CONFIGVALUE) VALUES (N'PMLifeTimeInHoursForDeletedEvents', '24')

/*Lifetime for events with "By Design" status (hours)*/
INSERT INTO APM.CONFIG (CONFIGNAME, CONFIGVALUE) VALUES (N'PMLifeTimeInHoursForByDesignEvents', '72')
END
GO

/*==============================================================*/
/* Index: IX_CONFIGNAME */
/*==============================================================*/
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CONFIG]') AND name = N'IX_CONFIGNAME'
)
BEGIN
CREATE UNIQUE INDEX IX_CONFIGNAME on APM.CONFIG (
CONFIGNAME ASC
)
END
GO

/*==============================================================*/
/* Table: CSAJAX */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.CSAJAX'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.CSAJAX (
CSAJAXID int identity,
CSEVENTID int not null,
URI nvarchar(255) not null,
NETWORKTIME decimal(35) null,
SERVERTIME decimal(35) null,
TOTALTIME decimal(35) null,
REQUESTSIZE bigint null,
RESPONSESIZE bigint null,
RESPONSETIME decimal(35) null,
SYNCHRONOUS bit not null,
LATENCY bigint null,
UTCDATE datetime null,
SOURCEID int null,
ISHEAVIESTNODE bit not null,
constraint PK_CSAJAX primary key (CSAJAXID)
)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSAJAX]') AND name = N'idx_W_EventURI'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_W_EventURI] ON [APM].[CSAJAX]
(
[CSEVENTID] ASC,
[URI] ASC
)
INCLUDE ( [TOTALTIME],
[SYNCHRONOUS]) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSAJAX]') AND name = N'FK_CSEVENTID'
)
BEGIN
CREATE NONCLUSTERED INDEX [FK_CSEVENTID] ON [APM].[CSAJAX]
(
[CSEVENTID] ASC
) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSAJAX]') AND name = N'idx_EventId'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_EventId] ON [APM].[CSAJAX]
(
[CSEVENTID] ASC
)
INCLUDE ( [TOTALTIME],
[RESPONSESIZE],
[LATENCY],
[SYNCHRONOUS],
[URI],
[NETWORKTIME],
[SERVERTIME],
[REQUESTSIZE]
) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSAJAX]') AND name = N'idx_EventIdTotalTime1'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_EventIdTotalTime1] ON APM.CSAJAX
(
[CSEVENTID] ASC,
[TOTALTIME] DESC
)
INCLUDE ( [URI],
[NETWORKTIME],
[SERVERTIME],
[RESPONSETIME],
[RESPONSESIZE],
[REQUESTSIZE],
[LATENCY]) WITH (SORT_IN_TEMPDB = ON) ON [PRIMARY]
END
GO

EXEC DomainTableRegisterIndexOptimization
@TableName = 'CSAJAX'
,@SchemaName = 'APM'
,@DatasetId = '$Config/DatasetId$'
GO


/*==============================================================*/
/* Table: CSASYNCAJAX */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.CSASYNCAJAX'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.CSASYNCAJAX (
CSASYNCAJAXID int identity,
CSEVENTID int not null,
HANDLERTIME decimal(35) null,
TOTALTIME decimal(35) null,
constraint PK_CSASYNCAJAX primary key (CSASYNCAJAXID)
)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSASYNCAJAX]') AND name = N'idx_EventId'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_EventId] ON APM.CSASYNCAJAX
(
[CSEVENTID] ASC
)
INCLUDE ([HANDLERTIME]) WITH (SORT_IN_TEMPDB = ON)
END
GO

EXEC DomainTableRegisterIndexOptimization
@TableName = 'CSASYNCAJAX'
,@SchemaName = 'APM'
,@DatasetId = '$Config/DatasetId$'
GO

/*==============================================================*/
/* Table: CSEVENT */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.CSEVENT'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.CSEVENT (
CSEVENTID int identity,
CSEVENTGROUPID int not null,
SOURCEID int not null,
MACHINEID int not null,
IPID int null,
CLASSTYPE nvarchar(50) not null,
EVENTCLASS nvarchar(50) null,
PAGEURI nvarchar(255) null,
DESCRIPTION nvarchar(255) not null,
BROWSER nvarchar(255) null,
UTCDATE datetime not null,
ROWGUID nvarchar(15) null,
SEVIEWERDBID int not null,
SEVIEWEREGID int not null,
USERID int null,
PMSTATUS tinyint not null,
TOTALTIME decimal(35) null,
TOTALSIZE bigint null,
LATENCY bigint null,
constraint PK_CSEVENT primary key (CSEVENTID)
)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSEVENT]') AND name = N'FK_USERS'
)
BEGIN
CREATE NONCLUSTERED INDEX FK_USERS ON APM.CSEVENT
(USERID)
END
GO

IF NOT EXISTS (
SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'CSEVENT' AND TABLE_SCHEMA = N'apm' AND COLUMN_NAME = 'PMSTATUS' AND COLUMN_DEFAULT IS NOT NULL
)
BEGIN
ALTER TABLE [APM].[CSEVENT] ADD CONSTRAINT [DF_CSEVENT_PMSTATUS] DEFAULT ((0)) FOR [PMSTATUS]
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSEVENT]') AND name = N'idx_DateSourceClassTypeMachine'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_DateSourceClassTypeMachine] ON [APM].[CSEVENT]
(
[UTCDATE] ASC,
[SOURCEID] ASC,
[CLASSTYPE] ASC,
[MACHINEID] ASC
)
INCLUDE ( [CSEVENTID],
[PAGEURI]) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSEVENT]') AND name = N'idx_ClassTypeDateMachineSource'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_ClassTypeDateMachineSource] ON [APM].[CSEVENT]
(
[CLASSTYPE] ASC,
[UTCDATE] ASC,
[MACHINEID] ASC,
[SOURCEID] ASC
)
INCLUDE([CSEVENTID],
PAGEURI) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSEVENT]') AND name = N'idx_SourceClassTypeDateMachine'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_SourceClassTypeDateMachine] ON [APM].[CSEVENT]
(
[SOURCEID] ASC,
[CLASSTYPE] ASC,
[UTCDATE] ASC,
[MACHINEID] ASC
)
INCLUDE([CSEVENTID],
PAGEURI) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSEVENT]') AND name = N'idx_SourceMachineClassTypeDate'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_SourceMachineClassTypeDate] ON [APM].[CSEVENT]
(
[SOURCEID] ASC,
[MACHINEID] ASC,
[CLASSTYPE] ASC,
[UTCDATE] ASC
)
INCLUDE ( [CSEVENTID],
[PAGEURI]) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSEVENT]') AND name = N'idx_DateSourceClassTypeMachineIpId'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_DateSourceClassTypeMachineIpId] ON [APM].[CSEVENT]
(
[UTCDATE] ASC,
[SOURCEID] ASC,
[CLASSTYPE] ASC,
[MACHINEID] ASC,
[IPID] ASC
)
INCLUDE ( [CSEVENTID],
[CSEVENTGROUPID],
[EVENTCLASS],
[PAGEURI],
[BROWSER],
[DESCRIPTION]) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSEVENT]') AND name = N'idx_SourceMachineEventClassDateIpId'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_SourceMachineEventClassDateIpId] ON [APM].[CSEVENT]
(
[SOURCEID] ASC,
[MACHINEID] ASC,
[EVENTCLASS] ASC,
[UTCDATE] ASC,
[IPID] ASC
)
INCLUDE ( [CSEVENTID],
[CSEVENTGROUPID],
[PAGEURI]) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSEVENT]') AND name = N'idx_DateSourceMachineEventClassIpId'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_DateSourceMachineEventClassIpId] ON [APM].[CSEVENT]
(
[UTCDATE] ASC,
[SOURCEID] ASC,
[MACHINEID] ASC,
[EVENTCLASS] ASC,
[IPID] ASC
)
INCLUDE ( [CSEVENTID],
[CSEVENTGROUPID],
[PAGEURI]) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSEVENT]') AND name = N'FK_IPID'
)
BEGIN
CREATE NONCLUSTERED INDEX [FK_IPID] ON [APM].[CSEVENT]
(
[IPID] ASC
)WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSEVENT]') AND name = N'FK_SOURCEID'
)
BEGIN
CREATE NONCLUSTERED INDEX [FK_SOURCEID] ON [APM].[CSEVENT]
(
[SOURCEID] ASC
) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSEVENT]') AND name = N'idx_SourceEventClassDateMachine'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_SourceEventClassDateMachine] ON [APM].[CSEVENT]
(
[SOURCEID] ASC,
[EVENTCLASS] ASC,
[UTCDATE] ASC,
[MACHINEID] ASC
)
INCLUDE ( [CSEVENTID],
[PAGEURI]) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSEVENT]') AND name = N'idx_DateSourceEventClassMachine'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_DateSourceEventClassMachine] ON [APM].[CSEVENT]
(
[UTCDATE] ASC,
[SOURCEID] ASC,
[EVENTCLASS] ASC,
[MACHINEID] ASC
)
INCLUDE ( [CSEVENTID],
[PAGEURI]) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSEVENT]') AND name = N'idx_ClassTypeSourceMachineDateIpId2'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_ClassTypeSourceMachineDateIpId2] ON [APM].[CSEVENT]
(
[CLASSTYPE] ASC,
[SOURCEID] ASC,
[MACHINEID] ASC,
[UTCDATE] ASC,
[IPID] ASC
)
INCLUDE ( [CSEVENTID],
[CSEVENTGROUPID],
[BROWSER],
[DESCRIPTION]) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSEVENT]') AND name = N'idx_W_PageSourceDate'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_W_PageSourceDate] ON [APM].[CSEVENT]
(
[PAGEURI] ASC,
[SOURCEID] ASC,
[UTCDATE] ASC
)
INCLUDE ( [CLASSTYPE],
[DESCRIPTION],
[ROWGUID],
[SEVIEWEREGID],
[MACHINEID],
[SEVIEWERDBID],
[IPID]) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSEVENT]') AND name = N'idx_SourceMachineClassTypeDateIpId'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_SourceMachineClassTypeDateIpId] ON [APM].[CSEVENT]
(
[SOURCEID] ASC,
[MACHINEID] ASC,
[CLASSTYPE] ASC,
[UTCDATE] ASC,
[IPID] ASC
)
INCLUDE ( [CSEVENTID],
[CSEVENTGROUPID],
[EVENTCLASS],
[PAGEURI],
[BROWSER],
[DESCRIPTION]) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSEVENT]') AND name = N'idx_W_IpIdSourcePageDate'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_W_IpIdSourcePageDate] ON [APM].[CSEVENT]
(
[IPID] ASC,
[SOURCEID] ASC,
[PAGEURI] ASC,
[UTCDATE] ASC
)
INCLUDE ( [CLASSTYPE],
[DESCRIPTION],
[ROWGUID],
[SEVIEWEREGID],
[MACHINEID],
[SEVIEWERDBID]
) WITH (SORT_IN_TEMPDB = ON)
END
GO
------------------------------ Summary User Analysis Indexes ------------------

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSEVENT]') AND name = N'idx_DateSource1'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_DateSource1] ON [APM].[CSEVENT]
(
[UTCDATE] ASC,
[SOURCEID] ASC
)
INCLUDE ( [CSEVENTID],
[CSEVENTGROUPID],
[PAGEURI],
[USERID],
[CLASSTYPE],
[EVENTCLASS],
[MACHINEID],
[BROWSER],
[DESCRIPTION],
[IPID],
[TOTALTIME]) WITH (SORT_IN_TEMPDB = ON) ON [PRIMARY]
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSEVENT]') AND name = N'idx_SourceDate1'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_SourceDate1] ON [APM].[CSEVENT]
(
[SOURCEID] ASC,
[UTCDATE] ASC
)
INCLUDE ( [CSEVENTID],
[CSEVENTGROUPID],
[PAGEURI],
[USERID],
[CLASSTYPE],
[EVENTCLASS],
[MACHINEID],
[BROWSER],
[DESCRIPTION],
[IPID],
[TOTALTIME]) WITH (SORT_IN_TEMPDB = ON) ON [PRIMARY]
END
GO

------------------------------ Transfer indexes--------------------------------
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSEVENT]') AND name = N'idx_T_RowGuid'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_T_RowGuid] ON [APM].[CSEVENT]
(
[ROWGUID] ASC
)WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSEVENT]') AND name = N'idx_T_RowGuid2'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_T_RowGuid2] ON APM.CSEVENT
(
[ROWGUID] ASC
)INCLUDE (UserId) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSEVENT]') AND name = N'idx_T_UtcDate'
)
BEGIN
CREATE INDEX idx_T_UtcDate ON APM.CSEVENT
(UTCDATE)
INCLUDE(SEVIEWERDBID) WITH (SORT_IN_TEMPDB = ON)
END
GO

---------------- delete old sources/computers wizard indexes --------------------
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[csevent]') AND name = N'idx_MachineDate'
)
BEGIN
CREATE INDEX idx_MachineDate ON APM.csevent (MACHINEID, UTCDATE DESC)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSEVENT]') AND name = N'idx_SM_PMStatusDate'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_SM_PMStatusDate] ON [APM].[CSEVENT]
(
[PMSTATUS] ASC,
[UTCDATE] ASC
)
INCLUDE ( [SEVIEWERDBID],
[CSEVENTID])
END
GO

EXEC DomainTableRegisterIndexOptimization
@TableName = 'CSEVENT'
,@SchemaName = 'APM'
,@DatasetId = '$Config/DatasetId$'
GO

/*==============================================================*/
/* Table: CSEVENTGROUP */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.CSEVENTGROUP'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.CSEVENTGROUP (
CSEVENTGROUPID int identity,
FIRSTEVENTDATE datetime not null,
LASTEVENTDATE datetime not null,
HASHVALUE nvarchar(50) null,
DESCRIPTION nvarchar(255) null,
SOURCEID int null,
constraint PK_CSEVENTGROUP primary key (CSEVENTGROUPID)
)
END
GO

------------------ Transfer indexes -----------------------
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSEventGroup]') AND name = N'idx_T_hashvalue'
)
BEGIN
CREATE INDEX idx_T_hashvalue on APM.CSEventGroup(hashvalue) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSEVENTGROUP]') AND name = N'idx_T_hashvalue2'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_T_hashvalue2] ON APM.CSEVENTGROUP
(
[HASHVALUE] ASC
) include (firsteventdate, lasteventdate, sourceid) WITH (SORT_IN_TEMPDB = ON)
END
GO

EXEC DomainTableRegisterIndexOptimization
@TableName = 'CSEVENTGROUP'
,@SchemaName = 'APM'
,@DatasetId = '$Config/DatasetId$'
GO

/*==============================================================*/
/* Table: CSEXEVENT */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.CSEXEVENT'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.CSEXEVENT (
CSEXEVENTID int identity,
CSEVENTID int not null,
ACTION nvarchar(255) not null,
EXMESSAGE nvarchar(255) not null,
EXTYPE nvarchar(255) not null,
EXFUNCTION nvarchar(255) not null,
ROWGUID nvarchar(15) null,
constraint PK_CSEXEVENT primary key (CSEXEVENTID)
)
END
GO

/*==============================================================*/
/* Table: CSHEAVIESTRESOURCE */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.CSHEAVIESTRESOURCE'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.CSHEAVIESTRESOURCE (
CSHEAVIESTRESOURCEID int identity,
CSEVENTID int not null,
NAME nvarchar(255) not null,
DURATION decimal(35) not null,
ROWGUID nvarchar(15) null,
ISHEAVIESTNODE bit not null,
constraint PK_CSHEAVIESTRESOURCE primary key (CSHEAVIESTRESOURCEID)
)
END
GO

IF NOT EXISTS (
SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'CSHEAVIESTRESOURCE' AND TABLE_SCHEMA = N'apm' AND COLUMN_NAME = 'IsHeaviestNode' AND COLUMN_DEFAULT IS NOT NULL
)
BEGIN
ALTER TABLE APM.CSHEAVIESTRESOURCE ADD CONSTRAINT DF_CSHEAVIESTRESOURCE_ISHAVIESTNODE DEFAULT 0 FOR IsHeaviestNode
END
GO

---------------------Transfer indexes---------------------
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSHEAVIESTRESOURCE]') AND name = N'idx_T_RowGuid'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_T_RowGuid] ON APM.CSHEAVIESTRESOURCE
(
[ROWGUID] ASC
) WITH (SORT_IN_TEMPDB = ON)
END
GO

EXEC DomainTableRegisterIndexOptimization
@TableName = 'CSHEAVIESTRESOURCE'
,@SchemaName = 'APM'
,@DatasetId = '$Config/DatasetId$'
GO

/*==============================================================*/
/* Table: CSJSCRIPTEVENT */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.CSJSCRIPTEVENT'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.CSJSCRIPTEVENT (
CSJSCRIPTEVENTID int identity,
CSEVENTID int not null,
ACTION nvarchar(255) not null,
TOTALTIME decimal(35) null,
UTCDATE datetime null,
SOURCEID int null,
constraint PK_CSJSCRIPTEVENT primary key (CSJSCRIPTEVENTID)
)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSJSCRIPTEVENT]') AND name = N'idx_W_ActionEvent'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_W_ActionEvent] ON [APM].[CSJSCRIPTEVENT]
(
[ACTION] ASC,
[CSEVENTID] ASC

) INCLUDE([TOTALTIME])
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSJSCRIPTEVENT]') AND name = N'idx_W_EventAction'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_W_EventAction] ON [APM].[CSJSCRIPTEVENT]
(
[CSEVENTID] ASC,
[ACTION] ASC

) INCLUDE([TOTALTIME])
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSJSCRIPTEVENT]') AND name = N'FK_CSEVENTID'
)
BEGIN
CREATE NONCLUSTERED INDEX [FK_CSEVENTID] ON [APM].[CSJSCRIPTEVENT]
(
[CSEVENTID] ASC
)WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSJSCRIPTEVENT]') AND name = N'idx_CSEvent1'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_CSEvent1] ON APM.CSJSCRIPTEVENT
(
[CSEVENTID] ASC
)
INCLUDE (
[TOTALTIME],
[ACTION]) WITH (SORT_IN_TEMPDB = ON)
END
GO

EXEC DomainTableRegisterIndexOptimization
@TableName = 'CSJSCRIPTEVENT'
,@SchemaName = 'APM'
,@DatasetId = '$Config/DatasetId$'
GO

/*==============================================================*/
/* Table: CSPAGEEVENT */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.CSPAGEEVENT'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.CSPAGEEVENT (
CSPAGEEVENTID int identity,
CSEVENTID int not null,
NETWORKTIME decimal(35) null,
SERVERTIME decimal(35) null,
DOMTIME decimal(35) null,
PERIPHERALTIME decimal(35) null,
ONLOADTIME decimal(35) null,
TOTALTIME decimal(35) null,
TOTALSIZE bigint null,
LATENCY bigint null,
UTCDATE datetime null,
SOURCEID int null,
constraint PK_CSPAGEEVENT primary key (CSPAGEEVENTID)
)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSPAGEEVENT]') AND name = N'FK_CSEVENTID'
)
BEGIN
CREATE NONCLUSTERED INDEX [FK_CSEVENTID] ON [APM].[CSPAGEEVENT]
(
[CSEVENTID] ASC
)WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSPAGEEVENT]') AND name = N'idx_EventId1'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_EventId1] ON [APM].[CSPAGEEVENT]
(
[CSEVENTID] ASC
)
INCLUDE ( [TOTALTIME],
[TOTALSIZE],
[NETWORKTIME],
[SERVERTIME],
[DOMTIME],
[PERIPHERALTIME],
[ONLOADTIME],
[LATENCY]
) WITH (SORT_IN_TEMPDB = ON)
END
GO

EXEC DomainTableRegisterIndexOptimization
@TableName = 'CSPAGEEVENT'
,@SchemaName = 'APM'
,@DatasetId = '$Config/DatasetId$'
GO

/*==============================================================*/
/* Table: CSPERIPHERAL */
/*==============================================================*/

IF (OBJECTPROPERTY(OBJECT_ID('APM.CSPERIPHERAL'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.CSPERIPHERAL (
CSPERIPHERALID int identity,
CSEVENTID int not null,
TYPE nvarchar(50) not null,
TOTALSIZE bigint null,
TOTALTIME decimal(35) null,
constraint PK_CSPERIPHERAL primary key (CSPERIPHERALID)
)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSPERIPHERAL]') AND name = N'FK_CSEVENTID'
)
BEGIN
CREATE NONCLUSTERED INDEX [FK_CSEVENTID] ON [APM].[CSPERIPHERAL]
(
[CSEVENTID] ASC
)WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSPERIPHERAL]') AND name = N'idx_EventId'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_EventId] ON [APM].[CSPERIPHERAL]
(
[CSEVENTID] ASC
)
INCLUDE ( [TYPE],
[TOTALSIZE]) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSPERIPHERAL]') AND name = N'idx_EventPeripheral'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_EventPeripheral] ON [APM].[CSPERIPHERAL]
(
[CSEVENTID] ASC,
[CSPERIPHERALID] ASC
)
INCLUDE ( [TYPE],
[TOTALSIZE]) WITH (SORT_IN_TEMPDB = ON)
END
GO

------------------------------ Transfer indexes -------------------------
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSPERIPHERAL]') AND name = N'idx_T_EventIdType'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_T_EventIdType] ON APM.CSPERIPHERAL
(
[CSEVENTID] ASC,
[TYPE] ASC
) WITH (SORT_IN_TEMPDB = ON)
END
GO

EXEC DomainTableRegisterIndexOptimization
@TableName = 'CSPERIPHERAL'
,@SchemaName = 'APM'
,@DatasetId = '$Config/DatasetId$'
GO

/*==============================================================*/
/* Table: CSPERIPHERALDETAIL */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.CSPERIPHERALDETAIL'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.CSPERIPHERALDETAIL (
CSPERIPHERALDETAILID int identity,
CSPERIPHERALID int not null,
DOMAIN nvarchar(255) not null,
PATH nvarchar(255) not null,
SIZE bigint null,
TOTALTIME decimal(35) null,
constraint PK_CSPERIPHERALDETAIL primary key (CSPERIPHERALDETAILID)
)
END
GO

/*==============================================================*/
/* Table: DATASET */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.DATASET'), 'IsTable') IS NULL)
BEGIN
-- Create table
CREATE TABLE APM.DATASET (
DATASETID int identity,
AGGREGATIONTYPEID int null,
DATASETNAME nvarchar(50) not null,
DEFAULTAGGREGATIONINTERVALCOUNT tinyint not null,
MAXDATAAGEDAYS int null,
AGGREGATIONMETHODNAME nvarchar(50) null,
constraint PK_DATASET primary key (DATASETID)
)

--Insert default values
INSERT into APM.dataset (
DATASETNAME
,DEFAULTAGGREGATIONINTERVALCOUNT
,AGGREGATIONTYPEID
,AGGREGATIONMETHODNAME
,MAXDATAAGEDAYS
)
values (
N'perfHourly',
40,
30,
N'PCounterAggregate',
91
)
END
GO

/*==============================================================*/
/* Table: DATASETAGGREGATIONHISTORY */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.DATASETAGGREGATIONHISTORY'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.DATASETAGGREGATIONHISTORY (
DATASETAGGREGATIONHISTORYID int identity,
DATASETID int not null,
AGGREGATIONDATETIME datetime not null,
DIRTYIND bit not null,
constraint PK_DATASETAGGREGATIONHISTORY primary key (DATASETAGGREGATIONHISTORYID)
)
END
GO

IF NOT EXISTS (
SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'DatasetAggregationHistory' AND TABLE_SCHEMA = N'apm' AND COLUMN_NAME = 'DirtyInd' AND COLUMN_DEFAULT IS NOT NULL
)
BEGIN
ALTER TABLE APM.DatasetAggregationHistory ADD CONSTRAINT DatasetAggregationHistoryID_Default DEFAULT 1 FOR DirtyInd
END
GO

--------------------------------------- Transfer indexes ----------------------
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[DATASETAGGREGATIONHISTORY]') AND name = N'idx_T_DIRTYIND_datasetid_date'
)
BEGIN
CREATE INDEX idx_T_DIRTYIND_datasetid_date ON APM.DATASETAGGREGATIONHISTORY
(
DIRTYIND, datasetid, AGGREGATIONDATETIME
)
WITH (SORT_IN_TEMPDB = ON)
END
GO

EXEC DomainTableRegisterIndexOptimization
@TableName = 'DATASETAGGREGATIONHISTORY'
,@SchemaName = 'APM'
,@DatasetId = '$Config/DatasetId$'
GO

/*==============================================================*/
/* Table: EVENT */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.EVENT'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.EVENT (
EVENTID bigint identity,
EVENTGROUPID int null,
RESOURCEID int null,
SOURCEID int null,
EVENTDURATION decimal(35) null,
MACHINEID int not null,
UTCEVENTDATE datetime not null,
EVENTCLASSTYPE nvarchar(50) null,
ROOTNODENAME nvarchar(255) null,
ASPECT nvarchar(50) null,
EXCEPTIONCLASS nvarchar(255) null,
DESCRIPTION nvarchar(255) null,
CATEGORY nvarchar(50) null,
HEAVYLIGHT int null,
ROWGUID nvarchar(15) null,
SEVIEWERDBID int null,
SEVIEWEREGID int not null,
IPID int null,
USERID int null,
PMSTATUS tinyint not null
)

ALTER TABLE APM.Event
ADD CONSTRAINT PK_EVENT PRIMARY KEY NONCLUSTERED (EVENTID)
END
GO

/*==============================================================*/
/* Index: IX_CDATE */
/*==============================================================*/
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[Event]') AND name = N'IX_CDATE'
)
BEGIN
CREATE CLUSTERED INDEX IX_CDATE ON APM.Event
(
UTCEVENTDATE ASC
)
END
GO

IF NOT EXISTS (
SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'EVENT' AND TABLE_SCHEMA = N'apm' AND COLUMN_NAME = 'PMSTATUS' AND COLUMN_DEFAULT IS NOT NULL
)
BEGIN
ALTER TABLE [APM].[EVENT] ADD CONSTRAINT [DF_EVENT_PMSTATUS] DEFAULT ((0)) FOR [PMSTATUS]
END
GO

--------------------- Change foreign key index--------------------------
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[EVENT]') AND name = N'FK_EVENTGROUP'
)
BEGIN
CREATE NONCLUSTERED INDEX [FK_EVENTGROUP] ON [APM].[EVENT]
(
[EVENTGROUPID] ASC
)
INCLUDE ( [EVENTDURATION],
[MACHINEID],
[UTCEVENTDATE],
[EVENTID],
[SOURCEID],
[EVENTCLASSTYPE],
[rootnodename],
[DESCRIPTION],
[CATEGORY]) WITH (SORT_IN_TEMPDB = ON)
END
GO

-----------------End Change foreign key index---------------------------
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[EVENT]') AND name = N'idx_DateSourceMachine'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_DateSourceMachine] ON [APM].[EVENT]
(
[UTCEVENTDATE] ASC,
[SOURCEID] ASC,
[MACHINEID] ASC
)
INCLUDE ( [EVENTGROUPID],
[EVENTDURATION],
[CATEGORY],
[HEAVYLIGHT],
[ASPECT],
[RESOURCEID],
[EVENTCLASSTYPE],
[USERID],
[EVENTID],
[DESCRIPTION],
[SEVIEWERDBID],
[ROOTNODENAME]) WITH (SORT_IN_TEMPDB = ON) ON [PRIMARY]
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[EVENT]') AND name = N'idx_MachineDate'
)
BEGIN
CREATE NONCLUSTERED INDEX idx_MachineDate ON APM.EVENT
(
MACHINEID
,UTCEVENTDATE
)
INCLUDE
(
SOURCEID
,EVENTGROUPID
,EVENTDURATION
,CATEGORY
,HEAVYLIGHT
,ASPECT
,RESOURCEID
,EVENTCLASSTYPE
,USERID
,EVENTID
,DESCRIPTION
,SEVIEWERDBID
,ROOTNODENAME
,[PMSTATUS]
)
WITH (SORT_IN_TEMPDB = ON) ON [PRIMARY]
END
GO

--------------------------------- Transfer indexes --------------
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[EVENT]') AND name = N'idx_T_RowGuid'
)
BEGIN
CREATE NONCLUSTERED INDEX idx_T_RowGuid ON APM.EVENT
(
ROWGUID
)
INCLUDE
(
HEAVYLIGHT
,IPID
,EVENTID
,USERID
)
WITH (SORT_IN_TEMPDB = ON) ON [PRIMARY]
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[EVENT]') AND name = N'idx_T_ResourceIdEventClassTypeDB'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_T_ResourceIdEventClassTypeDB] ON [APM].[EVENT]
(
[RESOURCEID] ASC,
[EVENTCLASSTYPE] ASC,
[SEVIEWERDBID] ASC
)
INCLUDE ( [HEAVYLIGHT],
[ROWGUID],
[EVENTID],
[SOURCEID],
[MACHINEID],
[EVENTDURATION]) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[EVENT]') AND name = N'idx_T_EventId'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_T_EventId] ON [APM].[EVENT]
(
[EVENTID] ASC
)
INCLUDE ( [SEVIEWERDBID],
[HEAVYLIGHT],
[ROWGUID],
[EXCEPTIONCLASS],
[DESCRIPTION],
[EVENTDURATION],
[SOURCEID],
[EVENTCLASSTYPE],
[RESOURCEID]) WITH (SORT_IN_TEMPDB = ON) ON [PRIMARY]
END
GO

----------------------- Event Window Indexes ----------------------
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[Event]') AND name = N'idx_W_ResourceDate'
)
BEGIN
CREATE INDEX idx_W_ResourceDate ON APM.Event
(ResourceId, UtcEventDate)
INCLUDE(
[SourceId],
[EventId],
[EventDuration],
[MACHINEID],
[EVENTCLASSTYPE],
[RootNodeName],
[DESCRIPTION],
[CATEGORY],
[ROWGUID],
[Aspect],
[HeavyLight],
[SEVIEWERDBID],
[SEVIEWEREGID],
[USERID],
[EVENTGROUPID]
) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[Event]') AND name = N'idx_W_SourceDate'
)
BEGIN
CREATE INDEX idx_W_SourceDate ON APM.Event
(SourceId, UtcEventDate)
INCLUDE(
[RESOURCEID],
[EventId],
[EventDuration],
[MACHINEID],
[EVENTCLASSTYPE],
[RootNodeName],
[DESCRIPTION],
[CATEGORY],
[ROWGUID],
[Aspect],
[HeavyLight],
[SEVIEWERDBID],
[SEVIEWEREGID],
[EVENTGROUPID],
[USERID]
) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[Event]') AND name = N'idx_W_RootDate'
)
BEGIN
CREATE INDEX idx_W_RootDate ON APM.Event
(RootNodeName, UTCEVENTDATE)
INCLUDE(
[SourceId],
[MachineId],
[RESOURCEID],
[EVENTID],
[EVENTDURATION],
[EVENTCLASSTYPE],
[DESCRIPTION],
[CATEGORY],
[ROWGUID],
[Aspect],
[Heavylight],
[SEVIEWERDBID],
[SEVIEWEREGID],
[EVENTGROUPID],
[USERID]
) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[EVENT]') AND name = N'idx_W_DescriptionDate'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_W_DescriptionDate] ON [APM].[EVENT]
(
[DESCRIPTION] ASC,
[UTCEVENTDATE] ASC
)
INCLUDE ( [SOURCEID],
[MACHINEID],
[RESOURCEID],
[ROOTNODENAME],
[CATEGORY],
[EVENTID],
[EVENTCLASSTYPE],
[ROWGUID],
[ASPECT],
[HEAVYLIGHT],
[SEVIEWERDBID],
[SEVIEWEREGID],
[USERID]) WITH (SORT_IN_TEMPDB = ON)
END
GO

/*==============================================================*/
/* Index: FK_EVENTRESOURCEID */
/*==============================================================*/
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[EVENT]') AND name = N'FK_EVENTRESOURCEID'
)
BEGIN
CREATE INDEX FK_EVENTRESOURCEID on APM.EVENT (
RESOURCEID ASC
)
END
GO

/*==============================================================*/
/* Index: FK_EVENTMACHINEID */
/*==============================================================*/
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[EVENT]') AND name = N'FK_EVENTMACHINEID'
)
BEGIN
CREATE INDEX FK_EVENTMACHINEID on APM.EVENT (
MACHINEID ASC
)
END
GO

/*==============================================================*/
/* Index: FK_EVENTSOURCEID */
/*==============================================================*/
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[EVENT]') AND name = N'FK_EVENTSOURCEID'
)
BEGIN
CREATE INDEX FK_EVENTSOURCEID on APM.EVENT (
SOURCEID ASC
)
END
GO

/*==============================================================*/
/* Index: FK_IPID */
/*==============================================================*/
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[EVENT]') AND name = N'FK_IPID'
)
BEGIN
CREATE INDEX FK_IPID on APM.EVENT (
IPID ASC
)
END
GO

/*==============================================================*/
/* Index: FK_SEVIEWERDBID */
/*==============================================================*/
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[EVENT]') AND name = N'FK_SEVIEWERDBID'
)
BEGIN
CREATE INDEX FK_SEVIEWERDBID on APM.EVENT (
SEVIEWERDBID ASC
)
END
GO

/*==============================================================*/
/* Index: FK_USERS */
/*==============================================================*/
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[EVENT]') AND name = N'FK_USERS'
)
BEGIN
CREATE INDEX FK_USERS on APM.EVENT (
USERID ASC
)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[EVENT]') AND name = N'idx_SM_PMStatusDate'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_SM_PMStatusDate] ON [APM].[EVENT]
(
[PMSTATUS] ASC,
[UTCEVENTDATE] ASC
)
INCLUDE ( [SEVIEWERDBID],
[EVENTID])
END
GO

EXEC DomainTableRegisterIndexOptimization
@TableName = 'EVENT'
,@SchemaName = 'APM'
,@DatasetId = '$Config/DatasetId$'
GO

/*==============================================================*/
/* Table: EVENTGROUP */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.EVENTGROUP'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.EVENTGROUP (
EVENTGROUPID int identity,
FIRSTEVENTDATE datetime null,
LASTEVENTDATE datetime null,
EVENTCLASSTYPE nvarchar(50) null,
ROOTNODENAME nvarchar(255) null,
ASPECT nvarchar(50) null,
HASHVALUE nvarchar(50) null,
DESCRIPTION nvarchar(255) null,
SOURCEID int null,
constraint PK_EVENTGROUP primary key (EVENTGROUPID)
)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[EVENTGROUP]') AND name = N'idx_EventGroupIdFirstEventDateSource'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_EventGroupIdFirstEventDateSource] ON [APM].[EVENTGROUP]
(
[EVENTGROUPID] ASC,
[FIRSTEVENTDATE] ASC,
[SOURCEID] ASC
) WITH (SORT_IN_TEMPDB = ON)
END
GO

-----------------------Transfer indexed----------------------
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[EVENTGROUP]') AND name = N'idx_EVENTGROUP_LASTEVENTDATE'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_EVENTGROUP_LASTEVENTDATE] ON APM.EVENTGROUP
(
[LASTEVENTDATE]
) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSEVENTGROUP]') AND name = N'idx_CSEVENTGROUP_LASTEVENTDATE'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_CSEVENTGROUP_LASTEVENTDATE] ON APM.CSEVENTGROUP
(
[LASTEVENTDATE]
) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[EVENTGROUP]') AND name = N'idx_T_hashvalue'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_T_hashvalue] ON [APM].[EVENTGROUP]
(
[HASHVALUE] ASC
) INCLUDE (firsteventdate, lasteventdate, sourceid) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[EVENTGROUP]') AND name = N'ix_T_hashvalue2'
)
BEGIN
CREATE NONCLUSTERED INDEX [ix_T_hashvalue2] ON [APM].[EVENTGROUP]
(
[HASHVALUE] ASC
) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[EVENTGROUP]') AND name = N'idx_EventGroupIdFirstEventDate'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_EventGroupIdFirstEventDate] ON APM.EVENTGROUP
(
[EVENTGROUPID] ASC,
[FIRSTEVENTDATE] ASC
)
WITH (SORT_IN_TEMPDB = ON)
END
GO

EXEC DomainTableRegisterIndexOptimization
@TableName = 'EVENTGROUP'
,@SchemaName = 'APM'
,@DatasetId = '$Config/DatasetId$'
GO

/*==============================================================*/
/* Table: EXCEPTIONNODE */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.EXCEPTIONNODE'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.EXCEPTIONNODE (
EXCEPTIONNODEID bigint identity,
EVENTID bigint not null,
RESOURCEID int null,
EXCEPTIONMESSAGE nvarchar(255) null,
EXCEPTIONCLASS nvarchar(255) null,
FUNCTIONNAME nvarchar(255) null,
RESOURCEMETHOD nvarchar(255) null,
MODULENAME nvarchar(255) null,
LINENUMBER bigint null,
DESCRIPTION nvarchar(255) null,
HASHCODE nvarchar(255) null,
ENTRYID int null,
ROWGUID nvarchar(15) null,
constraint PK_EXCEPTIONNODE primary key (EXCEPTIONNODEID)
)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[EXCEPTIONNODE]') AND name = N'idx_EVENTID'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_EVENTID] ON [APM].[EXCEPTIONNODE]
(
[EVENTID] ASC
)
INCLUDE ( [RESOURCEMETHOD]) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[EXCEPTIONNODE]') AND name = N'idx_ResourceExceptionEvent'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_ResourceExceptionEvent] ON [APM].[EXCEPTIONNODE]
(
[RESOURCEID] ASC,
[EXCEPTIONNODEID] ASC,
[EVENTID] ASC
)
INCLUDE ( [RESOURCEMETHOD]) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[EXCEPTIONNODE]') AND name = N'idx_EventIdResource2'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_EventIdResource2] ON [APM].[EXCEPTIONNODE]
(
[EVENTID] ASC,
[ResourceId] ASC
)
INCLUDE ( [RESOURCEMETHOD]) WITH (SORT_IN_TEMPDB = ON)
END
GO

----------------------Summary User Analysis Report -------------------
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[ExceptionNode]') AND name = N'idx_EventIdResource'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_EventIdResource] ON [APM].[ExceptionNode]
(
[EVENTID] ASC,
[RESOURCEID] ASC
)
INCLUDE ( [DESCRIPTION]) WITH (SORT_IN_TEMPDB = ON)
END
GO

----------------------Transfer indexes ------------------------------
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[EXCEPTIONNODE]') AND name = N'idx_T_eventIdResourceId'
)
BEGIN
CREATE INDEX idx_T_eventIdResourceId on APM.exceptionnode(eventid, resourceid) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[EXCEPTIONNODE]') AND name = N'idx_T_rowguid'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_T_rowguid] ON [APM].[EXCEPTIONNODE]
(
[ROWGUID] ASC
) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[EXCEPTIONNODE]') AND name = N'idx_T_eventId'
)
BEGIN
CREATE INDEX idx_T_eventId on APM.EXCEPTIONNODE(eventid)
INCLUDE(resourceid) WITH (SORT_IN_TEMPDB = ON)
END
GO

----------------------- Event Window indexes ---------------------------------
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[ExceptionNode]') AND name = N'idx_W_ResourceMethod'
)
BEGIN
CREATE INDEX idx_W_ResourceMethod on APM.ExceptionNode (RESOURCEMETHOD) INCLUDE(Eventid) WITH (SORT_IN_TEMPDB = ON)
END
GO

/*==============================================================*/
/* Index: IX_XDATA_HASHCODE */
/*==============================================================*/
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[EXCEPTIONNODE]') AND name = N'IX_XDATA_HASHCODE'
)
BEGIN
create index IX_XDATA_HASHCODE on APM.EXCEPTIONNODE (
HASHCODE ASC
)
END
GO

/*==============================================================*/
/* Index: FK_EXCEPTIONNODERESOURCEID */
/*==============================================================*/
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[EXCEPTIONNODE]') AND name = N'FK_EXCEPTIONNODERESOURCEID'
)
BEGIN
create index FK_EXCEPTIONNODERESOURCEID on APM.EXCEPTIONNODE (
RESOURCEID ASC
)
END
GO

/*==============================================================*/
/* Index: FK_EXCEPTIONNODEEVENTID */
/*==============================================================*/
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[EXCEPTIONNODE]') AND name = N'FK_EXCEPTIONNODEEVENTID'
)
BEGIN
create index FK_EXCEPTIONNODEEVENTID on APM.EXCEPTIONNODE (
EVENTID ASC
)
END
GO

/*==============================================================*/
/* Index: FK_EXCEPTIONNODEEVENTIDRESOURCEID */
/*==============================================================*/
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[EXCEPTIONNODE]') AND name = N'FK_EXCEPTIONNODEEVENTIDRESOURCEID'
)
BEGIN
create index FK_EXCEPTIONNODEEVENTIDRESOURCEID on APM.EXCEPTIONNODE (
EVENTID ASC,
RESOURCEID ASC
)
END
GO

EXEC DomainTableRegisterIndexOptimization
@TableName = 'EXCEPTIONNODE'
,@SchemaName = 'APM'
,@DatasetId = '$Config/DatasetId$'
GO

/*==============================================================*/
/* Table: IP */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.IP'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.IP (
IPID int identity,
IP nvarchar(50) not null,
SUBNETC nvarchar(50) not null,
constraint PK_IP primary key (IPID)
)
END
GO

IF NOT EXISTS
(
SELECT * FROM INFORMATION_SCHEMA.table_constraints WHERE TABLE_NAME = N'IP' AND TABLE_SCHEMA = N'apm' AND CONSTRAINT_NAME=N'uniq_ip'
)
BEGIN
ALTER TABLE APM.ip ADD CONSTRAINT uniq_ip UNIQUE (ip)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[IP]') AND name = N'idx_IP'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_IP] ON [APM].[IP]
(
[IPID] ASC
)
INCLUDE ([SUBNETC]) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[IP]') AND name = N'idx_IPSubnetC'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_IPSubnetC] ON [APM].[IP]
(
[IPID] ASC,
[SUBNETC] ASC
)
END
GO

EXEC DomainTableRegisterIndexOptimization
@TableName = 'IP'
,@SchemaName = 'APM'
,@DatasetId = '$Config/DatasetId$'
GO

/*==============================================================*/
/* Table: MACHINE */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.MACHINE'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.MACHINE (
MACHINEID int identity,
MACHINE nvarchar(255) NOT NULL,
WINDOWSVERSION nvarchar(50) NULL,
AGENTVERSION nvarchar(50) NULL,
CPUCOUNT int NULL,
CONSTRAINT PK_MACHINE primary key (MACHINEID),
CONSTRAINT UC_MACHINE_MACHINE UNIQUE (MACHINE)
)
END
GO

/*==============================================================*/
/* Index: IX_MACHINE */
/*==============================================================*/
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[MACHINE]') AND name = N'IX_MACHINE'
)
BEGIN
create unique index IX_MACHINE on APM.MACHINE (
MACHINE ASC
)
END
GO

/*==============================================================*/
/* Table: MEMBER */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.MEMBER'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.MEMBER (
MEMBERID int not null,
LOGINNAME nvarchar(50) not null,
MEMBERPASSWORD nvarchar(255) null,
FIRSTNAME nvarchar(50) null,
LASTNAME nvarchar(50) null,
EMAIL nvarchar(255) null,
USERDATA ntext null,
USERTYPE char(1) null,
constraint PK_MEMBER primary key nonclustered (MEMBERID)
)
END
GO

/*==============================================================*/
/* Index: IX_LOGINNAME */
/*==============================================================*/
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[MEMBER]') AND name = N'IX_LOGINNAME'
)
BEGIN
create unique index IX_LOGINNAME on APM.MEMBER (
LOGINNAME ASC
)
END
GO

/*==============================================================*/
/* Table: MEMBERAPPLICATION */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.MEMBERAPPLICATION'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.MEMBERAPPLICATION (
MEMBERAPPLICATIONID int not null,
APPLICATIONID int null,
MEMBERID int null,
constraint PK_MEMBERAPPLICATION primary key nonclustered (MEMBERAPPLICATIONID)
)
END
GO

/*==============================================================*/
/* Index: FK_FK_APPLICATION */
/*==============================================================*/
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[MEMBERAPPLICATION]') AND name = N'FK_FK_APPLICATION'
)
BEGIN
create index FK_FK_APPLICATION on APM.MEMBERAPPLICATION (
APPLICATIONID ASC
)
END
GO

/*==============================================================*/
/* Index: FK_FK_USER */
/*==============================================================*/
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[MEMBERAPPLICATION]') AND name = N'FK_FK_USER'
)
BEGIN
create index FK_FK_USER on APM.MEMBERAPPLICATION (
MEMBERID ASC
)
END
GO

/*==============================================================*/
/* Table: MESSAGES */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.MESSAGES'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.MESSAGES (
ID int not null,
MESSAGE nvarchar(max) not null,
constraint PK_MESSAGES primary key (ID)
)

insert APM.messages values(50002, N'stored procedure %s: sp_xml_preparedocument has returned error code %d ')
insert APM.messages values(50004, N'There was an error %d. Severity level: %d Error state: %d Procedure: %s Line: %d Message: %s ')
INSERT APM.MESSAGES VALUES(50006, N'stored procedure %s: Event with RowGuid %s was not found.')
INSERT APM.MESSAGES VALUES(50007, N'FillGroups: document is empty.')
INSERT APM.MESSAGES VALUES(50008, N'FillGroups: Inserted %d resource group.')
INSERT APM.MESSAGES VALUES(50010, N'FillGroups: Inserted %d resource group node.')
INSERT APM.MESSAGES VALUES(50011, N'FILLINTERNALRESOURCES: performance events exist without performance nodes.')
INSERT APM.MESSAGES VALUES(50012, N'FILLINTERNALRESOURCES: exception events exist without exception nodes.')
INSERT APM.MESSAGES VALUES(50013, N'FILLRESOURCES: #DETAILS is empty.')
INSERT APM.MESSAGES VALUES(50014, N'FILLRESOURCES: INSERTED INTO RESOURCE %d record(s).')
INSERT APM.MESSAGES VALUES(50015, N'FILLRESOURCES: heaviest nodes exist.')
INSERT APM.MESSAGES VALUES(50016, N'FILLRESOURCES: Performance node is missing for the heaviest resource.')
INSERT APM.MESSAGES VALUES(50017, N'FILLRESOURCES: Created %d performancenode record(s) for missing heaviest nodes.')
INSERT APM.MESSAGES VALUES(50018, N'FILLRESOURCES: Updated %d performancenode record(s) for resources that contain references to the resource group node.')
INSERT APM.MESSAGES VALUES(50019, N'FILLRESOURCES: Updated %d performancenode record(s) for resources that do not contains references to the resource group node.')
INSERT APM.MESSAGES VALUES(50020, N'FILLRESOURCES: Updated %d event record(s). Save references to the top heaviest resource.')
INSERT APM.MESSAGES VALUES(50021, N'FILLRESOURCES: Updated %d exceptionnode record(s). Save references to the exception method.')
INSERT APM.MESSAGES VALUES(50022, N'FILLRESOURCES: Updated %d event record(s). Save references to the exception method.')
INSERT APM.MESSAGES VALUES(50023, N'GROOMINGWORKTABLES: Deleted %d record(s) from %s table.')

INSERT APM.MESSAGES VALUES(50024, N'CLIENTEVENT_SYNC: Inserted %d record(s) into %s table.')
INSERT APM.MESSAGES VALUES(50025, N'CLIENTEVENT_SYNC: performance events exist.')
INSERT APM.MESSAGES VALUES(50026, N'CLIENTEVENT_SYNC: AJAX events exist.')

INSERT APM.MESSAGES VALUES(50027, N'FILLINTERNALRESOURCES: Resource group nodes were not found.')
INSERT APM.MESSAGES VALUES(50028, N'FILLINTERNALRESOURCES: Processed %d record(s). Inserted %d record(s) into the performance node table.')
INSERT APM.MESSAGES VALUES(50029, N'FILLINTERNALRESOURCES: Inserted %d record(s) into the exception node table.')
INSERT APM.MESSAGES VALUES(50030, N'stored procedure %s: Event with RowGuid %s was not found.')

INSERT APM.MESSAGES VALUES(50031, N'FILLRESOURCEGROUPNODES: Resource group node is missing.')
INSERT APM.MESSAGES VALUES(50032, N'%s: Inserted %d record(s) into %s table.')
INSERT APM.MESSAGES VALUES(50033, N'GroomingWorkTables: package size %d, period(days) %d, reporting grooming date %s.')
INSERT APM.MESSAGES VALUES(50034, N'GROOMINGWORKTABLES: pmstatus - %d lifetime - %d (hours) last keep date - %s.')
INSERT APM.MESSAGES VALUES(50035, N'FILLINTERNALRESOURCES: rowguid(s) "%s" or "%s" have not been found.')
END
GO

/*==============================================================*/
/* Table: OPERATION */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.OPERATION'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.OPERATION (
OPERATIONID int not null,
OPERATIONNAME nvarchar(50) not null,
REPEATCOUNTONFAILED int not null,
constraint PK_OPERATION primary key (OPERATIONID)
)

insert into APM.operation values(1, 'extraction', 0)
insert into APM.operation values(2, 'transform', 0)
insert into APM.operation values(3, 'insert', 0)
insert into APM.operation values(4, 'update', 0)
insert into APM.operation values(5, 'aggregate', 0)
insert into APM.operation values(6, 'grooming', 0)
insert into APM.operation values(7, 'constraints', 0)
insert into APM.operation values(8, 'resource', 0)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[OPERATION]') AND name = N'OperationName_IX'
)
BEGIN
CREATE UNIQUE INDEX OperationName_IX ON APM.OPERATION (OperationName)
END
GO

EXEC DomainTableRegisterIndexOptimization
@TableName = 'OPERATION'
,@SchemaName = 'APM'
,@DatasetId = '$Config/DatasetId$'
GO

/*==============================================================*/
/* Table: PCDESCRIPTION */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.PCDESCRIPTION'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.PCDESCRIPTION (
PCDESCRIPTIONID int identity,
NAME nvarchar(255) not null,
DESCRIPTION ntext null,
constraint PK_PCDESCRIPTION primary key (PCDESCRIPTIONID)
)
END
GO

/*==============================================================*/
/* Index: IX_NAME */
/*==============================================================*/
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PCDESCRIPTION]') AND name = N'IX_NAME'
)
BEGIN
create unique index IX_NAME on APM.PCDESCRIPTION (
NAME ASC
)
END
GO

/*==============================================================*/
/* Table: PCPROCESS */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.PCPROCESS'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.PCPROCESS (
PCPROCESSID int identity,
PROCESS nvarchar(255) NULL,
EXTRATYPE int NULL,
EXTRAINFO nvarchar(255) NULL,
HASHVALUE nvarchar(50) NULL,
CONSTRAINT PK_PCPROCESS primary key (PCPROCESSID),
CONSTRAINT UC_PCPROCESS_HASHVALUE UNIQUE (HASHVALUE)
)
END
GO

------------------------------ Transfer indexes -------------------------
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[pcprocess]') AND name = N'idx_T_hashvalue'
)
BEGIN
CREATE index idx_T_hashvalue on APM.pcprocess(hashvalue) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PCPROCESS]') AND name = N'idx_PCProcessId'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_PCProcessId] ON [APM].[PCPROCESS]
(
[PCPROCESSID]
)
INCLUDE
(
[EXTRAINFO],
[PROCESS]
)
WITH (SORT_IN_TEMPDB = OFF)
END
GO

EXEC DomainTableRegisterIndexOptimization
@TableName = 'PCPROCESS'
,@SchemaName = 'APM'
,@DatasetId = '$Config/DatasetId$'
GO

/*==============================================================*/
/* Table: PCTYPE */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.PCTYPE'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.PCTYPE (
PCTYPEID int identity,
TYPE nvarchar(255) NOT NULL,
MEASURE nvarchar(50) NULL,
INSTANCEFUNCTION nvarchar(50) NULL,
DATEFUNCTION nvarchar(50) NULL,
CONSTRAINT PK_PCTYPE primary key (PCTYPEID),
CONSTRAINT UC_PCTYPE_TYPE UNIQUE (TYPE)
)
END
GO

/*==============================================================*/
/* Index: IX_TYPE */
/*==============================================================*/
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PCTYPE]') AND name = N'IX_TYPE'
)
BEGIN
create unique index IX_TYPE on APM.PCTYPE (
TYPE ASC
)
END
GO

/*==============================================================*/
/* Table: PERFDAILY */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.PERFDAILY'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.PERFDAILY (
PERFDAILYID bigint identity,
PCTYPEID int not null,
MACHINEID int not null,
SOURCEID int null,
PCPROCESSID int null,
IS_STATE int null,
UTCDATE datetime not null,
SUMVALUE decimal(18,4) not null,
AVERAGEVALUE decimal(18,4) not null,
SAMPLECOUNT int not null,
MINVALUE decimal(18,4) not null,
MAXVALUE decimal(18,4) not null,
PACKAGECOUNTER int not null
)
END
GO

/*==============================================================*/
/* Index: IX_CDATE */
/*==============================================================*/

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PerfDaily]') AND name = N'IX_CDATE'
)
BEGIN
CREATE CLUSTERED INDEX IX_CDATE ON APM.PerfDaily
(
UTCDATE ASC
)
END
GO

IF NOT EXISTS
(
SELECT * FROM INFORMATION_SCHEMA.table_constraints WHERE TABLE_NAME = N'PERFDAILY' AND TABLE_SCHEMA = N'apm' AND CONSTRAINT_NAME=N'PK_PERFDAILY'
)
BEGIN
ALTER TABLE APM.PERFDAILY ADD CONSTRAINT PK_PERFDAILY PRIMARY KEY (PERFDAILYID)
END
GO

/*==============================================================*/
/* Index: FK_PERFDAILYMACHINEID */
/*==============================================================*/

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PERFDAILY]') AND name = N'FK_PERFDAILYMACHINEID'
)
BEGIN
create index FK_PERFDAILYMACHINEID on APM.PERFDAILY (
MACHINEID ASC
)
END
GO

/*==============================================================*/
/* Index: FK_PERFDAILYSOURCEID */
/*==============================================================*/

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PERFDAILY]') AND name = N'FK_PERFDAILYSOURCEID'
)
BEGIN
create index FK_PERFDAILYSOURCEID on APM.PERFDAILY (
SOURCEID ASC
)
END
GO

/*==============================================================*/
/* Index: FK_PERFDAILYPROCESSID */
/*==============================================================*/

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PERFDAILY]') AND name = N'FK_PERFDAILYPROCESSID'
)
BEGIN
create index FK_PERFDAILYPROCESSID on APM.PERFDAILY (
PCPROCESSID ASC
)
END
GO

/*==============================================================*/
/* Index: FK_PERFDAILYTYPEID */
/*==============================================================*/
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PERFDAILY]') AND name = N'FK_PERFDAILYTYPEID'
)
BEGIN
create index FK_PERFDAILYTYPEID on APM.PERFDAILY (
PCTYPEID ASC
)
END
GO

EXEC DomainTableRegisterIndexOptimization
@TableName = 'PERFDAILY'
,@SchemaName = 'APM'
,@DatasetId = '$Config/DatasetId$'
GO

/*==============================================================*/
/* Table: PERFHOURLY */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.PERFHOURLY'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.PERFHOURLY (
PERFHOURLYID bigint identity,
PCTYPEID int not null,
MACHINEID int not null,
SOURCEID int null,
PCPROCESSID int null,
IS_STATE int null,
UTCDATE datetime not null,
AVERAGEVALUE float(53) not null,
MINVALUE float(53) not null,
MAXVALUE float(53) not null,
SAMPLECOUNT bigint not null,
SUMVALUE float(53) not null,
PACKAGECOUNTER bigint not null,
HASHVALUE nvarchar(50) null
)
END
GO

/*==============================================================*/
/* Index: IX_CDATE */
/*==============================================================*/

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PERFHOURLY]') AND name = N'IX_CDATE'
)
BEGIN
CREATE CLUSTERED INDEX IX_CDATE ON APM.PERFHOURLY
(
UTCDATE ASC
)
END
GO

IF NOT EXISTS
(
SELECT * FROM INFORMATION_SCHEMA.table_constraints WHERE TABLE_NAME = N'PERFHOURLY' AND TABLE_SCHEMA = N'apm' AND CONSTRAINT_NAME=N'PK_PERFHOURLY'
)
BEGIN
ALTER TABLE APM.PERFHOURLY ADD CONSTRAINT PK_PERFHOURLY PRIMARY KEY (PERFHOURLYID)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PERFHOURLY]') AND name = N'IX_AGGREGATE'
)
BEGIN
CREATE NONCLUSTERED INDEX IX_AGGREGATE ON APM.PERFHOURLY
(
[PCTYPEID] ASC,
[MACHINEID] ASC,
[SOURCEID] ASC,
[PCPROCESSID] ASC,
[IS_STATE] ASC,
[UTCDATE] ASC,
[SUMVALUE] ASC
)
END
GO

--------------------- Summary Performance &amp; Summary Failure &amp; Problem Distribution ----------------------
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PERFHOURLY]') AND name = N'idx_TypeSourceMachineDate'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_TypeSourceMachineDate] ON [APM].[PERFHOURLY]
(
[PCTYPEID] ASC,
[SOURCEID] ASC,
[MACHINEID] ASC,
[UTCDATE] ASC
)
INCLUDE ([SUMVALUE], [MAXVALUE], [SAMPLECOUNT], [PACKAGECOUNTER], [PCPROCESSID])
WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PERFHOURLY]') AND name = N'idx_DateTypeSourceMachine'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_DateTypeSourceMachine] ON [APM].[PERFHOURLY]
(
[UTCDATE] ASC,
[PCTYPEID] ASC,
[SOURCEID] ASC,
[MACHINEID] ASC
)
INCLUDE ([SUMVALUE], [MAXVALUE], [SAMPLECOUNT], [PACKAGECOUNTER], [PCPROCESSID])
WITH (SORT_IN_TEMPDB = ON)
END
GO


IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PERFHOURLY]') AND name = N'idx_MachineSourceDateType'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_MachineSourceDateType] ON [APM].[PERFHOURLY]
(
[MACHINEID] ASC,
[SOURCEID] ASC,
[UTCDATE] ASC,
[PCTYPEID] ASC
)
INCLUDE ( [SAMPLECOUNT],
[SUMVALUE],
[MAXVALUE],
[PACKAGECOUNTER],
[PCPROCESSID]) WITH (SORT_IN_TEMPDB = ON)
END
GO


IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PERFHOURLY]') AND name = N'idx_SourceMachineDateType'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_SourceMachineDateType] ON [APM].[PERFHOURLY]
(
[SOURCEID] ASC,
[MACHINEID] ASC,
[UTCDATE] ASC,
[PCTYPEID] ASC
)
INCLUDE ( [SAMPLECOUNT],
[SUMVALUE],
[MAXVALUE],
[PACKAGECOUNTER],
[PCPROCESSID])
WITH (SORT_IN_TEMPDB = ON)
END
GO


IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PERFHOURLY]') AND name = N'idx_TypeDateSourceMachine'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_TypeDateSourceMachine] ON [APM].[PERFHOURLY]
(
[PCTYPEID] ASC,
[UTCDATE] ASC,
[SOURCEID] ASC,
[MACHINEID] ASC
)
INCLUDE ( [SAMPLECOUNT],
[SUMVALUE],
[MAXVALUE],
[PACKAGECOUNTER],
[PCPROCESSID])
WITH (SORT_IN_TEMPDB = ON)
END
GO

--------------------- Application Status -------------------------

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PERFHOURLY]') AND name = N'idx_SourceId'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_SourceId] ON [APM].[PERFHOURLY]
(
[SOURCEID] ASC
)
INCLUDE ([PCPROCESSID])
WITH (SORT_IN_TEMPDB = ON)
END
GO


IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PERFHOURLY]') AND name = N'idx_ProcessId'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_ProcessId] ON [APM].[PERFHOURLY]
(
[PCPROCESSID]ASC
)
INCLUDE ([SOURCEID])
WITH (SORT_IN_TEMPDB = ON)
END
GO


IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PERFHOURLY]') AND name = N'idx_SourceProcessMachine'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_SourceProcessMachine] ON [APM].[PERFHOURLY]
(
[SOURCEID] ASC,
[PCPROCESSID] ASC,
[MACHINEID] ASC
)
WITH (SORT_IN_TEMPDB = ON)
END
GO


IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PERFHOURLY]') AND name = N'idx_ProcessSourceMachine'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_ProcessSourceMachine] ON [APM].[PERFHOURLY]
(
[PCPROCESSID] ASC,
[SOURCEID] ASC,
[MACHINEID] ASC
)
WITH (SORT_IN_TEMPDB = ON)
END
GO


IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PERFHOURLY]') AND name = N'idx_MachineProcessSource'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_MachineProcessSource] ON [APM].[PERFHOURLY]
(
[MACHINEID] ASC,
[PCPROCESSID] ASC,
[SOURCEID] ASC
)
WITH (SORT_IN_TEMPDB = ON)
END
GO

--------------------- Transfer indexes -----------------------------

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PERFHOURLY]') AND name = N'idx_T_hashvalue'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_T_hashvalue] ON [APM].[PERFHOURLY]
(
[HASHVALUE] ASC
)
INCLUDE (
[MINVALUE],
[MAXVALUE],
[SAMPLECOUNT],
[SUMVALUE],
[PACKAGECOUNTER])
WITH (SORT_IN_TEMPDB = ON)
END
GO


/*==============================================================*/
/* Index: FK_PERFHOURLYMACHINEID */
/*==============================================================*/

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PERFHOURLY]') AND name = N'FK_PERFHOURLYMACHINEID'
)
BEGIN
CREATE INDEX FK_PERFHOURLYMACHINEID on APM.PERFHOURLY (
MACHINEID ASC
)
END
GO

/*==============================================================*/
/* Index: FK_PERFHOURLYSOURCEID */
/*==============================================================*/

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PERFHOURLY]') AND name = N'FK_PERFHOURLYSOURCEID'
)
BEGIN
create index FK_PERFHOURLYSOURCEID on APM.PERFHOURLY (
SOURCEID ASC
)
END
GO

/*==============================================================*/
/* Index: FK_PERFHOURLYPCTYPEID */
/*==============================================================*/
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PERFHOURLY]') AND name = N'FK_PERFHOURLYPCTYPEID'
)
BEGIN
CREATE INDEX FK_PERFHOURLYPCTYPEID on APM.PERFHOURLY (
PCTYPEID ASC
)
END
GO

/*==============================================================*/
/* Index: FK_PERFHOURLYPCPROCESSID */
/*==============================================================*/
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PERFHOURLY]') AND name = N'FK_PERFHOURLYPCPROCESSID'
)
BEGIN
CREATE INDEX FK_PERFHOURLYPCPROCESSID on APM.PERFHOURLY (
PCPROCESSID ASC
)
END
GO

EXEC DomainTableRegisterIndexOptimization
@TableName = 'PERFHOURLY'
,@SchemaName = 'APM'
,@DatasetId = '$Config/DatasetId$'
GO

/*==============================================================*/
/* Table: PERFORMANCENODE */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.PERFORMANCENODE'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.PERFORMANCENODE (
PERFORMANCENODEID bigint identity,
EVENTID bigint not null,
RESOURCEID int null,
RESOURCEGROUPNODEID int null,
DESCRIPTION nvarchar(255) null,
FUNCTIONNAME nvarchar(255) null,
RESOURCEMETHOD nvarchar(255) null,
DURATION decimal(35) not null,
HASHCODE nvarchar(255) null,
ENTRYID int not null,
SELFDURATION decimal(35) null,
ROWGUID nvarchar(15) null,
ISHEAVIESTNODE bit not null,
constraint PK_PERFORMANCENODE primary key (PERFORMANCENODEID)
)
END
GO

IF NOT EXISTS (
SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'PERFORMANCENODE' AND TABLE_SCHEMA = N'apm' AND COLUMN_NAME = 'IsHeaviestNode' AND COLUMN_DEFAULT IS NOT NULL
)
BEGIN
ALTER TABLE APM.PERFORMANCENODE ADD CONSTRAINT DF_PERFORMANCENODE_ISHAVIESTNODE DEFAULT 0 FOR IsHeaviestNode
END
GO

------------------------ Application Performance index-----------
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PERFORMANCENODE]') AND name = N'idx_EventIdResourceIdSelfDuration1'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_EventIdResourceIdSelfDuration1] ON [APM].[PERFORMANCENODE]
(
[EVENTID] ASC,
[RESOURCEID] ASC,
[SELFDURATION] ASC
)
INCLUDE ( [RESOURCEMETHOD]) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PERFORMANCENODE]') AND name = N'idx_EventIdResourceIdDuration'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_EventIdResourceIdDuration] ON [APM].[PERFORMANCENODE]
(
[EVENTID] ASC,
[RESOURCEID] ASC,
[DURATION] ASC
)
INCLUDE ( [RESOURCEMETHOD]) WITH (SORT_IN_TEMPDB = ON)
END
GO

------------------------ Transfer indexes ------------------------------
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[performancenode]') AND name = N'idx_T_eventIdResourceId'
)
BEGIN
CREATE INDEX idx_T_eventIdResourceId on APM.performancenode(eventid, resourceid)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[performanceNode]') AND name = N'idx_T_EventIdEntryId'
)
BEGIN
CREATE INDEX idx_T_EventIdEntryId on APM.performanceNode(EventId, EntryId) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PERFORMANCENODE]') AND name = N'idx_T_EventId'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_T_EventId] ON [APM].[PERFORMANCENODE]
(
[EVENTID]
)
INCLUDE ( [PerformanceNodeId],[RESOURCEMETHOD], ResourceGroupNodeId, [EntryId], [RESOURCEID], [SELFDURATION])
WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[performancenode]') AND name = N'idx_T_RowGuid'
)
BEGIN
CREATE INDEX idx_T_RowGuid on APM.performancenode(rowguid)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PERFORMANCENODE]') AND name = N'idx_T_ResourceIdEventId'
)
BEGIN
CREATE INDEX idx_T_ResourceIdEventId ON APM.PERFORMANCENODE
(
RESOURCEID,
EVENTID
) WITH (SORT_IN_TEMPDB = ON)
END
GO

----------------------- Event Window Indexes ----------------------
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PerformanceNode]') AND name = N'idx_W_EventIdResourceIdSelfDuration2'
)
BEGIN
CREATE INDEX idx_W_EventIdResourceIdSelfDuration2 on APM.PerformanceNode
(
EventId, ResourceId, SelfDuration Desc
)
INCLUDE(
[Description],
[DURATION],
[ENTRYID]
) WITH (SORT_IN_TEMPDB = ON)
END
GO

/*==============================================================*/
/* Index: FK_PERFORMANCENODERESOURCEID */
/*==============================================================*/
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PERFORMANCENODE]') AND name = N'FK_PERFORMANCENODERESOURCEID'
)
BEGIN
create index FK_PERFORMANCENODERESOURCEID on APM.PERFORMANCENODE (
RESOURCEID ASC
)
END
GO

/*==============================================================*/
/* Index: FK_PERFORMANCENODERESOURCEGROUPID */
/*==============================================================*/
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PERFORMANCENODE]') AND name = N'FK_PERFORMANCENODERESOURCEGROUPID'
)
BEGIN
create index FK_PERFORMANCENODERESOURCEGROUPID on APM.PERFORMANCENODE (
RESOURCEGROUPNODEID ASC
)
END
GO

/*==============================================================*/
/* Index: FK_PERFORMANCENODEEVENTID */
/*==============================================================*/
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PERFORMANCENODE]') AND name = N'FK_PERFORMANCENODEEVENTID'
)
BEGIN
create index FK_PERFORMANCENODEEVENTID on APM.PERFORMANCENODE (
EVENTID ASC
)
END
GO

/*==============================================================*/
/* Index: FK_PERFORMANCENODEVENTIDRESOURCEID */
/*==============================================================*/
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PERFORMANCENODE]') AND name = N'FK_PERFORMANCENODEVENTIDRESOURCEID'
)
BEGIN
CREATE INDEX FK_PERFORMANCENODEVENTIDRESOURCEID on APM.PERFORMANCENODE (
EVENTID ASC,
RESOURCEID ASC
)
END
GO

EXEC DomainTableRegisterIndexOptimization
@TableName = 'PERFORMANCENODE'
,@SchemaName = 'APM'
,@DatasetId = '$Config/DatasetId$'
GO

/*==============================================================*/
/* Table: RELATIVEDATES */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.RELATIVEDATES'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.RELATIVEDATES (
ID int not null,
NAME nvarchar(255) not null,
ORDERBY int not null
)

INSERT INTO APM.RELATIVEDATES VALUES(0, '', 0)

INSERT INTO APM.RelativeDates([Id], [Name], [OrderBy])
SELECT 10, 'This Week: First Day', 6
UNION ALL
SELECT 20, 'This Week: Last Day', 7
UNION ALL
SELECT 30, 'Previous Week: First Day', 10
UNION ALL
SELECT 40, 'Previous Week: Last Day', 11
UNION ALL
SELECT 50, 'This Month: First Day', 4
UNION ALL
SELECT 60, 'This Month: Last Day', 5
UNION ALL
SELECT 70, 'Previous Month: First Day', 8
UNION ALL
SELECT 80, 'Previous Month: Last Day', 9
UNION ALL
SELECT 90, 'Today', 1
UNION ALL
SELECT 100, 'Yesterday', 2
END
GO


/*==============================================================*/
/* Table: RESOURCE */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.RESOURCE'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.RESOURCE (
RESOURCEID int identity,
RESOURCEGROUPID int not null,
SOURCEID int not null,
RESOURCEURIFORMAT nvarchar(255) not null,
RESOURCEURI nvarchar(255) not null,
constraint PK_RESOURCE primary key (RESOURCEID)
)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[RESOURCE]') AND name = N'idx_GroupResourceUri'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_GroupResourceUri] ON [APM].[RESOURCE]
(
[RESOURCEGROUPID] ASC,
[RESOURCEID] ASC,
[RESOURCEURI] ASC
)WITH (SORT_IN_TEMPDB = ON)
END
GO

------------------------ Transfer indexes -----------------------
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[RESOURCE]') AND name = N'idx_T_SourceResourceUri'
)
BEGIN
CREATE INDEX idx_T_SourceResourceUri ON APM.RESOURCE(sourceId, resourceUri)
include(resourceid, resourcegroupid) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[RESOURCE]') AND name = N'idx_T_ResGroupUri'
)
BEGIN
CREATE INDEX idx_T_ResGroupUri ON APM.RESOURCE(ResourceGroupId, ResourceUri) include (sourceId, resourceid)
WITH (SORT_IN_TEMPDB = ON)
END
GO

------------------------ Event WINDOW indexes -----------------------
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[RESOURCE]') AND name = N'idx_W_ResourceUri'
)
BEGIN
CREATE INDEX idx_W_ResourceUri ON APM.RESOURCE (ResourceUri) INCLUDE(ResourceGroupId) WITH (SORT_IN_TEMPDB = ON)
END
GO

/*==============================================================*/
/* Index: FK_RESOURCERESOURCEGROUPID */
/*==============================================================*/
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[RESOURCE]') AND name = N'FK_RESOURCERESOURCEGROUPID'
)
BEGIN
create index FK_RESOURCERESOURCEGROUPID on APM.RESOURCE (
RESOURCEGROUPID ASC
)
END
GO

/*==============================================================*/
/* Index: FK_RESOURCESOURCEID */
/*==============================================================*/
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[RESOURCE]') AND name = N'FK_RESOURCESOURCEID'
)
BEGIN
CREATE INDEX FK_RESOURCESOURCEID on APM.RESOURCE (
SOURCEID ASC
)
END
GO

EXEC DomainTableRegisterIndexOptimization
@TableName = 'RESOURCE'
,@SchemaName = 'APM'
,@DatasetId = '$Config/DatasetId$'
GO

/*==============================================================*/
/* Table: RESOURCEGROUP */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.RESOURCEGROUP'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.RESOURCEGROUP (
RESOURCEGROUPID int identity,
NAME nvarchar(255) not null,
constraint PK_RESOURCEGROUP primary key (RESOURCEGROUPID)
)
END
GO

/*==============================================================*/
/* Table: RESOURCEGROUPNODE */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.RESOURCEGROUPNODE'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.RESOURCEGROUPNODE (
RESOURCEGROUPNODEID int identity,
EVENTID bigint not null,
RESOURCEGROUPID int not null,
DURATION bigint not null,
CALLCOUNT int null,
constraint PK_RESOURCEGROUPNODE primary key (RESOURCEGROUPNODEID)
)
END
GO

---------------------- Application Performance index-----------
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[RESOURCEGROUPNODE]') AND name = N'idx_EventIdResourceGroupNodeIdResourceGroupId'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_EventIdResourceGroupNodeIdResourceGroupId] ON [APM].[RESOURCEGROUPNODE]
(
[EVENTID] ASC,
[RESOURCEGROUPNODEID] ASC,
[RESOURCEGROUPID] ASC
)
INCLUDE ( [DURATION]) WITH (SORT_IN_TEMPDB = ON)
END
GO

/*==============================================================*/
/* Index: FK_RESOURCEGROUPNODERESOURCEGROUPID */
/*==============================================================*/
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[RESOURCEGROUPNODE]') AND name = N'FK_RESOURCEGROUPNODERESOURCEGROUPID'
)
BEGIN
CREATE INDEX FK_RESOURCEGROUPNODERESOURCEGROUPID on APM.RESOURCEGROUPNODE (
RESOURCEGROUPID ASC
)
END
GO

/*==============================================================*/
/* Index: FK_RESOURCEGROUPNODEEVENTID */
/*==============================================================*/
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[RESOURCEGROUPNODE]') AND name = N'FK_RESOURCEGROUPNODEEVENTID'
)
BEGIN
CREATE INDEX FK_RESOURCEGROUPNODEEVENTID on APM.RESOURCEGROUPNODE (
EVENTID ASC
)
END
GO

EXEC DomainTableRegisterIndexOptimization
@TableName = 'RESOURCEGROUPNODE'
,@SchemaName = 'APM'
,@DatasetId = '$Config/DatasetId$'
GO

/*==============================================================*/
/* Table: SEVIEWERDB */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.SEVIEWERDB'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.SEVIEWERDB (
SEVIEWERDBID int identity,
DATABASEID uniqueidentifier not null,
ADDRESS nvarchar(max) null,
constraint PK_SEVIEWERDB primary key (SEVIEWERDBID)
)
END
GO

IF NOT EXISTS
(
SELECT * FROM INFORMATION_SCHEMA.table_constraints WHERE TABLE_NAME = N'SEVIEWERDB' AND TABLE_SCHEMA = N'apm' AND CONSTRAINT_NAME=N'database_id_uniq'
)
BEGIN
ALTER TABLE APM.SEVIEWERDB add constraint database_id_uniq unique(databaseId)
END
GO

/*==============================================================*/
/* Table: SOURCE */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.SOURCE'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.SOURCE (
SOURCEID int identity,
SOURCE nvarchar(255) NOT NULL,
CONSTRAINT PK_SOURCE primary key (SOURCEID),
CONSTRAINT UC_SOURCE_SOURCE UNIQUE (SOURCE)
)
END
GO

/*==============================================================*/
/* Index: IX_SOURCE */
/*==============================================================*/
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[SOURCE]') AND name = N'IX_SOURCE'
)
BEGIN
create unique index IX_SOURCE on APM.SOURCE (
SOURCE ASC
)
END
GO

/*==============================================================*/
/* Table: TASKS */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.TASKS'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.TASKS (
TASKID int identity,
TABLENAME nvarchar(50) not null,
STARTDATE datetime null,
ENDDATE datetime null,
OPERATIONID int not null,
LASTTIMESTAMP bigint null,
STATUS nvarchar(50) null,
SEVIEWERDBID int null,
constraint PK_TASKS primary key (TASKID)
)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[TASKS]') AND name = N'idx_T_TableNameDatabase'
)
BEGIN
CREATE INDEX idx_T_TableNameDatabase ON APM.TASKS
(tablename, seviewerdbid) INCLUDE(lasttimestamp)
END
GO

EXEC DomainTableRegisterIndexOptimization
@TableName = 'TASKS'
,@SchemaName = 'APM'
,@DatasetId = '$Config/DatasetId$'
GO

/*==============================================================*/
/* Table: TIMEZONE */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.TIMEZONE'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.TIMEZONE (
NAME nvarchar(255) null,
OFFSET int null
)

INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT-12:00', -720)
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT-11:00', -660)
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT-10:00', -600)
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT-9:00', -540)
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT-8:00', -480)
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT-7:00', -420)
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT-6:00', -360)
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT-5:00', -300)
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT-4:00', -240)
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT-3:30', -210)
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT-3:00', -180)
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT-2:00', -120)
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT-1:00', -60)
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT-0:00', 0)
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT+1:00', 60)
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT+2:00', 120)
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT+3:00', 180)
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT+3:30', 210)
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT+4:00', 240)
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT+4:30', 270)
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT+5:00', 300)
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT+5:30', 330)
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT+5:45', 345)
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT+6:00', 360)
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT+6:30', 390)
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT+7:00', 420)
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT+8:00', 480)
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT+9:00', 540)
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT+9:30', 570)
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT+10:00', 600)
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT+11:00', 660)
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT+12:00', 720)
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT+13:00', 780)

/* Daylight Saving time zones*/
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT-2:30', -150)
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT+6:45', 405)
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT+10:30', 630)
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT+14:00', 840)
END
GO

/*==============================================================*/
/* Table: USERS */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.USERS'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.USERS (
USERID int identity,
NAME nvarchar(255) not null,
constraint PK_USERS primary key (USERID)
)
END
GO

IF NOT EXISTS
(
SELECT * FROM INFORMATION_SCHEMA.table_constraints WHERE TABLE_NAME = N'Users' AND TABLE_SCHEMA = N'apm' AND CONSTRAINT_NAME=N'Name_Unique'
)
BEGIN
ALTER TABLE [APM].[Users] ADD CONSTRAINT Name_Unique UNIQUE (NAME)
END
GO

/*==============================================================*/
/* Table: EVENTDETAIL */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.EVENTDETAIL'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE [APM].[EVENTDETAIL](
[EVENTDETAILID] [int] IDENTITY(1,1) NOT NULL,
[EVENTID] [bigint] NULL,
[NAME] [nvarchar](50) NULL,
[VALUE] [nvarchar](255) NULL,
[VALUETYPE] [nvarchar](50) NULL
CONSTRAINT [PK_EVENTDETAIL] PRIMARY KEY CLUSTERED
(
[EVENTDETAILID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
END
GO

/****** Object: Index [IX_EVENTID] ******/

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[EVENTDETAIL]') AND name = N'IX_EVENTID'
)
BEGIN
CREATE NONCLUSTERED INDEX [IX_EVENTID] ON [APM].[EVENTDETAIL]
(
[EVENTID] ASC
)WITH (MAXDOP = 1, SORT_IN_TEMPDB = ON, ONLINE = OFF) ON [PRIMARY]
END
GO

EXEC DomainTableRegisterIndexOptimization
@TableName = 'EVENTDETAIL'
,@SchemaName = 'APM'
,@DatasetId = '$Config/DatasetId$'
GO

/*==============================================================*/
/* Table: CSEVENTDETAIL */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.CSEVENTDETAIL'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE [APM].[CSEVENTDETAIL](
[CSEVENTDETAILID] [int] IDENTITY(1,1) NOT NULL,
[CSEVENTID] [int] NULL,
[NAME] [nvarchar](50) NULL,
[VALUE] [nvarchar](255) NULL,
[VALUETYPE] [nvarchar](50) NULL
CONSTRAINT [PK_CSEVENTDETAIL] PRIMARY KEY CLUSTERED
(
[CSEVENTDETAILID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
END
GO

/****** Object: Index [[IX_CSEVENTID]] ******/

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSEVENTDETAIL]') AND name = N'IX_CSEVENTID'
)
BEGIN
CREATE NONCLUSTERED INDEX [IX_CSEVENTID] ON [APM].[CSEVENTDETAIL]
(
[CSEVENTID] ASC
)WITH (MAXDOP = 1, SORT_IN_TEMPDB = ON, ONLINE = OFF) ON [PRIMARY]
END
GO

EXEC DomainTableRegisterIndexOptimization
@TableName = 'CSEVENTDETAIL'
,@SchemaName = 'APM'
,@DatasetId = '$Config/DatasetId$'
GO

/*==============================================================*/
/* View: V_APPLICATIONSOURCEMACHINE */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.V_APPLICATIONSOURCEMACHINE'), 'IsView') IS NULL)
BEGIN
EXECUTE('CREATE VIEW APM.V_APPLICATIONSOURCEMACHINE
AS
select clmn=1')
END
GO

ALTER VIEW APM.V_APPLICATIONSOURCEMACHINE as
SELECT A.APPLICATIONID, B.SOURCEID, M.MACHINEID, A.APPLICATION, B.SOURCE, M.MACHINE AS MACHINENAME
FROM APM.APPLICATION A
INNER JOIN APM.APPLICATIONSOURCEMACHINE C ON A.APPLICATIONID = C.APPLICATIONID
LEFT JOIN APM.SOURCE B ON B.SOURCEID = C.SOURCEID
LEFT JOIN APM.MACHINE M ON M.MACHINEID = C.MACHINEID
GO

/*==============================================================*/
/* View: V_EVENTWINDOW */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.V_EVENTWINDOW'), 'IsView') IS NULL) BEGIN
EXECUTE('CREATE VIEW APM.V_EVENTWINDOW
AS
select clmn=1')
END
GO

ALTER VIEW APM.V_EVENTWINDOW as
SELECT E.EVENTID, E.EVENTGROUPID, E.CATEGORY, E.DESCRIPTION, E.EVENTDURATION, E.ROOTNODENAME,
E.UTCEVENTDATE, E.EVENTCLASSTYPE, E.ASPECT,E.EXCEPTIONCLASS, E.RESOURCEID, E.ROWGUID, E.HEAVYLIGHT,E.SEVIEWEREGID,
S.SOURCE, S.SOURCEID, M.MACHINE, M.MACHINEID, SDB.ADDRESS AS PATH,
E.USERID,USR.NAME AS USERNAME, E.PMSTATUS
FROM APM.EVENT (NOLOCK) AS E INNER JOIN APM.SOURCE AS S ON S.SOURCEID=E.SOURCEID
INNER JOIN APM.MACHINE (NOLOCK) AS M ON M.MACHINEID=E.MACHINEID
INNER JOIN APM.SEVIEWERDB (NOLOCK) AS SDB ON SDB.SEVIEWERDBID=E.SEVIEWERDBID
LEFT JOIN APM.USERS (NOLOCK) AS USR ON E.USERID=USR.USERID
GO

/* foreign key to trace */
if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_PMSERVEREVENTTRACE_PMTRACE')
BEGIN
ALTER TABLE APM.PMSERVEREVENTTRACE ADD CONSTRAINT FK_PMSERVEREVENTTRACE_PMTRACE FOREIGN KEY (PMTRACEID) REFERENCES APM.PMTRACE(PMTRACEID)
END
GO

/* foreign key to event delete cascade */
if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_PMSERVEREVENTTRACE_PMEVENT')
BEGIN
ALTER TABLE APM.PMSERVEREVENTTRACE ADD CONSTRAINT FK_PMSERVEREVENTTRACE_PMEVENT FOREIGN KEY (EVENTID) REFERENCES APM.EVENT(EVENTID) ON DELETE CASCADE
END
GO

GO
/* foreign key to trace */
if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_PMCLIENTEVENTTRACE_PMTRACE')
BEGIN
ALTER TABLE APM.PMCLIENTEVENTTRACE ADD CONSTRAINT FK_PMCLIENTEVENTTRACE_PMTRACE FOREIGN KEY (PMTRACEID) REFERENCES APM.PMTRACE(PMTRACEID)
END
GO

/* foreign key to csevent delete cascade */
if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_PMCLIENTEVENTTRACE_PMEVENT')
BEGIN
ALTER TABLE APM.PMCLIENTEVENTTRACE ADD CONSTRAINT FK_PMCLIENTEVENTTRACE_PMEVENT FOREIGN KEY (CSEVENTID) REFERENCES APM.CSEVENT(CSEVENTID) ON DELETE CASCADE
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_EVENTDET_REFERENCE_EVENT')
BEGIN
ALTER TABLE [APM].[EVENTDETAIL] WITH CHECK ADD CONSTRAINT [FK_EVENTDET_REFERENCE_EVENT] FOREIGN KEY([EVENTID])
REFERENCES [APM].[EVENT] ([EVENTID])
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_CSEVENTDET_REFERENCE_CSEVENT')
BEGIN
ALTER TABLE [APM].[CSEVENTDETAIL] WITH CHECK ADD CONSTRAINT [FK_CSEVENTDET_REFERENCE_CSEVENT] FOREIGN KEY([CSEVENTID])
REFERENCES [APM].[CSEVENT] ([CSEVENTID])
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_APPLICAT_FK_APPLIC_APPLICAT')
BEGIN
alter table APM.APPLICATIONSOURCEMACHINE
add constraint FK_APPLICAT_FK_APPLIC_APPLICAT foreign key (APPLICATIONID)
references APM.APPLICATION (APPLICATIONID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_APPLICAT_FK_MACHIN_MACHINE')
BEGIN
alter table APM.APPLICATIONSOURCEMACHINE
add constraint FK_APPLICAT_FK_MACHIN_MACHINE foreign key (MACHINEID)
references APM.MACHINE (MACHINEID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_APPLICAT_FK_SOURCE_SOURCE')
BEGIN
alter table APM.APPLICATIONSOURCEMACHINE
add constraint FK_APPLICAT_FK_SOURCE_SOURCE foreign key (SOURCEID)
references APM.SOURCE (SOURCEID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_CSAJAX_REFERENCE_CSEVENT')
BEGIN
alter table APM.CSAJAX
add constraint FK_CSAJAX_REFERENCE_CSEVENT foreign key (CSEVENTID)
references APM.CSEVENT (CSEVENTID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_CSASYNCA_REFERENCE_CSEVENT')
BEGIN
alter table APM.CSASYNCAJAX
add constraint FK_CSASYNCA_REFERENCE_CSEVENT foreign key (CSEVENTID)
references APM.CSEVENT (CSEVENTID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_CSEVENT_REFERENCE_MACHINE')
BEGIN
alter table APM.CSEVENT
add constraint FK_CSEVENT_REFERENCE_MACHINE foreign key (MACHINEID)
references APM.MACHINE (MACHINEID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_CSEVENT_REFERENCE_SOURCE')
BEGIN
alter table APM.CSEVENT
add constraint FK_CSEVENT_REFERENCE_SOURCE foreign key (SOURCEID)
references APM.SOURCE (SOURCEID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_CSEVENT_REFERENCE_CSEVENTG')
BEGIN
alter table APM.CSEVENT
add constraint FK_CSEVENT_REFERENCE_CSEVENTG foreign key (CSEVENTGROUPID)
references APM.CSEVENTGROUP (CSEVENTGROUPID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_CSEVENT_REFERENCE_IP')
BEGIN
alter table APM.CSEVENT
add constraint FK_CSEVENT_REFERENCE_IP foreign key (IPID)
references APM.IP (IPID)
END
GO

IF NOT EXISTS
(
SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = N'FK_CSEVENT_USERS'
)
BEGIN
alter table APM.CSEVENT
add constraint FK_CSEVENT_USERS foreign key (USERID)
references APM.USERS (USERID)
END
GO

IF NOT EXISTS
(
SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = N'FK_CSEXEVEN_REFERENCE_CSEVENT'
)
BEGIN
alter table APM.CSEXEVENT
add constraint FK_CSEXEVEN_REFERENCE_CSEVENT foreign key (CSEVENTID)
references APM.CSEVENT (CSEVENTID)
END
GO

IF NOT EXISTS
(
SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = N'FK_CSHEAVIE_REFERENCE_CSEVENT'
)
BEGIN
alter table APM.CSHEAVIESTRESOURCE
add constraint FK_CSHEAVIE_REFERENCE_CSEVENT foreign key (CSEVENTID)
references APM.CSEVENT (CSEVENTID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_CSJSCRIP_REFERENCE_CSEVENT')
BEGIN
alter table APM.CSJSCRIPTEVENT
add constraint FK_CSJSCRIP_REFERENCE_CSEVENT foreign key (CSEVENTID)
references APM.CSEVENT (CSEVENTID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_CSPAGEEV_REFERENCE_CSEVENT')
BEGIN
alter table APM.CSPAGEEVENT
add constraint FK_CSPAGEEV_REFERENCE_CSEVENT foreign key (CSEVENTID)
references APM.CSEVENT (CSEVENTID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_CSPERIPH_REFERENCE_CSEVENT')
BEGIN
alter table APM.CSPERIPHERAL
add constraint FK_CSPERIPH_REFERENCE_CSEVENT foreign key (CSEVENTID)
references APM.CSEVENT (CSEVENTID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_CSPERIPH_REFERENCE_CSPERIPH')
BEGIN
alter table APM.CSPERIPHERALDETAIL
add constraint FK_CSPERIPH_REFERENCE_CSPERIPH foreign key (CSPERIPHERALID)
references APM.CSPERIPHERAL (CSPERIPHERALID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_DATASET_AGGREGATION')
BEGIN
alter table APM.DATASET
add constraint FK_DATASET_AGGREGATION foreign key (AGGREGATIONTYPEID)
references APM.AGGREGATIONTYPE (AGGREGATIONTYPEID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_DATASET_HISTORY')
BEGIN
alter table APM.DATASETAGGREGATIONHISTORY
add constraint FK_DATASET_HISTORY foreign key (DATASETID)
references APM.DATASET (DATASETID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_EVENT_FK_EVENTG_EVENTGRO')
BEGIN
alter table APM.EVENT
add constraint FK_EVENT_FK_EVENTG_EVENTGRO foreign key (EVENTGROUPID)
references APM.EVENTGROUP (EVENTGROUPID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_EVENT_FK_EVENT__IP')
BEGIN
alter table APM.EVENT
add constraint FK_EVENT_FK_EVENT__IP foreign key (IPID)
references APM.IP (IPID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_EVENT_FK_EVENT__SEVIEWER')
BEGIN
alter table APM.EVENT
add constraint FK_EVENT_FK_EVENT__SEVIEWER foreign key (SEVIEWERDBID)
references APM.SEVIEWERDB (SEVIEWERDBID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_EVENT_FK_SOURCE_SOURCE')
BEGIN
alter table APM.EVENT
add constraint FK_EVENT_FK_SOURCE_SOURCE foreign key (SOURCEID)
references APM.SOURCE (SOURCEID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_EVENT_REFERENCE_MACHINE')
BEGIN
alter table APM.EVENT
add constraint FK_EVENT_REFERENCE_MACHINE foreign key (MACHINEID)
references APM.MACHINE (MACHINEID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_EVENT_REFERENCE_RESOURCE')
BEGIN
alter table APM.EVENT
add constraint FK_EVENT_REFERENCE_RESOURCE foreign key (RESOURCEID)
references APM.RESOURCE (RESOURCEID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_EVENT_USERS')
BEGIN
alter table APM.EVENT
add constraint FK_EVENT_USERS foreign key (USERID)
references APM.USERS (USERID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_EXCEPTIO_FK_EXCEPT_EVENT')
BEGIN
alter table APM.EXCEPTIONNODE
add constraint FK_EXCEPTIO_FK_EXCEPT_EVENT foreign key (EVENTID)
references APM.EVENT (EVENTID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_EXCEPTIO_REFERENCE_RESOURCE')
BEGIN
alter table APM.EXCEPTIONNODE
add constraint FK_EXCEPTIO_REFERENCE_RESOURCE foreign key (RESOURCEID)
references APM.RESOURCE (RESOURCEID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_MEMBERAP_FK_APPLIC_APPLICAT')
BEGIN
alter table APM.MEMBERAPPLICATION
add constraint FK_MEMBERAP_FK_APPLIC_APPLICAT foreign key (APPLICATIONID)
references APM.APPLICATION (APPLICATIONID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_MEMBERAP_FK_USER_MEMBER')
BEGIN
alter table APM.MEMBERAPPLICATION
add constraint FK_MEMBERAP_FK_USER_MEMBER foreign key (MEMBERID)
references APM.MEMBER (MEMBERID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_PERFDAYLY_TYPE')
BEGIN
alter table APM.PERFDAILY
add constraint FK_PERFDAYLY_TYPE foreign key (PCTYPEID)
references APM.PCTYPE (PCTYPEID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_PERFDAYLY_MACHINE')
BEGIN
alter table APM.PERFDAILY
add constraint FK_PERFDAYLY_MACHINE foreign key (MACHINEID)
references APM.MACHINE (MACHINEID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_PERFDAYLY_SOURCE')
BEGIN
alter table APM.PERFDAILY
add constraint FK_PERFDAYLY_SOURCE foreign key (SOURCEID)
references APM.SOURCE (SOURCEID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_PERFDAIL_REFERENCE_PCPROCES')
BEGIN
alter table APM.PERFDAILY
add constraint FK_PERFDAIL_REFERENCE_PCPROCES foreign key (PCPROCESSID)
references APM.PCPROCESS (PCPROCESSID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_PERFHOURLY_PCTYPE')
BEGIN
alter table APM.PERFHOURLY
add constraint FK_PERFHOURLY_PCTYPE foreign key (PCTYPEID)
references APM.PCTYPE (PCTYPEID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_PERFHOURLY_MACHINE')
BEGIN
alter table APM.PERFHOURLY
add constraint FK_PERFHOURLY_MACHINE foreign key (MACHINEID)
references APM.MACHINE (MACHINEID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_PERFHOURLY_SOURCE')
BEGIN
alter table APM.PERFHOURLY
add constraint FK_PERFHOURLY_SOURCE foreign key (SOURCEID)
references APM.SOURCE (SOURCEID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_PERFHOUR_REFERENCE_PCPROCES')
BEGIN
alter table APM.PERFHOURLY
add constraint FK_PERFHOUR_REFERENCE_PCPROCES foreign key (PCPROCESSID)
references APM.PCPROCESS (PCPROCESSID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_PERFORMANCENODE_EVENT')
BEGIN
alter table APM.PERFORMANCENODE
add constraint FK_PERFORMANCENODE_EVENT foreign key (EVENTID)
references APM.EVENT (EVENTID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_PERFORMA_REFERENCE_RESOURCEGROUP')
BEGIN
alter table APM.PERFORMANCENODE
add constraint FK_PERFORMA_REFERENCE_RESOURCEGROUP foreign key (RESOURCEGROUPNODEID)
references APM.RESOURCEGROUPNODE (RESOURCEGROUPNODEID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_PERFORMA_REFERENCE_RESOURCE')
BEGIN
alter table APM.PERFORMANCENODE
add constraint FK_PERFORMA_REFERENCE_RESOURCE foreign key (RESOURCEID)
references APM.RESOURCE (RESOURCEID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_RESOURCE_REFERENCE_RESOURCE')
BEGIN
alter table APM.RESOURCE
add constraint FK_RESOURCE_REFERENCE_RESOURCE foreign key (RESOURCEGROUPID)
references APM.RESOURCEGROUP (RESOURCEGROUPID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_RESOURCE_REFERENCE_SOURCE')
BEGIN
alter table APM.RESOURCE
add constraint FK_RESOURCE_REFERENCE_SOURCE foreign key (SOURCEID)
references APM.SOURCE (SOURCEID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_RESOURCE_REFERENCE_RESOURCENODE')
BEGIN
alter table APM.RESOURCEGROUPNODE
add constraint FK_RESOURCE_REFERENCE_RESOURCENODE foreign key (RESOURCEGROUPID)
references APM.RESOURCEGROUP (RESOURCEGROUPID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_RESOURCE_REFERENCE_EVENT')
BEGIN
alter table APM.RESOURCEGROUPNODE
add constraint FK_RESOURCE_REFERENCE_EVENT foreign key (EVENTID)
references APM.EVENT (EVENTID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_TASKS_TaskMode')
BEGIN
alter table APM.TASKS
add constraint FK_TASKS_TaskMode foreign key (OPERATIONID)
references APM.OPERATION (OPERATIONID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_TASKS_REFERENCE_SEVIEWER')
BEGIN
alter table APM.TASKS
add constraint FK_TASKS_REFERENCE_SEVIEWER foreign key (SEVIEWERDBID)
references APM.SEVIEWERDB (SEVIEWERDBID)
END
GO

/*==============================================================*/
/* Common security reporting functions */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.FN_ADMINUSER'), 'IsScalarFunction') IS NULL)
BEGIN
EXECUTE('CREATE FUNCTION APM.FN_ADMINUSER ()
RETURNS int
AS begin return 1 end')
END
GO


/*==============================================================*/
/* Function: FN_ADMINUSER */
/*==============================================================*/
ALTER FUNCTION APM.FN_ADMINUSER(@USERNAME NVARCHAR(100))
RETURNS INT AS
BEGIN
DECLARE @A INT
SET @A = (SELECT MEMBERID FROM APM.MEMBER WHERE LOGINNAME = @USERNAME AND USERTYPE='a')
RETURN @A
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.FN_ISSECURE'), 'IsScalarFunction') IS NULL)
BEGIN
EXECUTE('CREATE FUNCTION APM.FN_ISSECURE ()
RETURNS int
AS begin return 1 end')
END
GO

/*==============================================================*/
/* Function: FN_ISSECURE */
/*==============================================================*/

ALTER FUNCTION APM.FN_ISSECURE ()
RETURNS INT AS
BEGIN
DECLARE @A INT
SELECT @A = CAST(CAST(CONFIGVALUE AS NCHAR) AS INT) FROM APM.CONFIG WHERE CONFIGNAME = 'SECURITYMODE'
RETURN @A
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.DATASETAGGREGATE'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.DATASETAGGREGATE AS RETURN 1')
END
GO
ALTER PROCEDURE APM.DATASETAGGREGATE
@DATASETNAME NVARCHAR(50)
,@DESCRIPTORS NTEXT
,@AGGREGATIONTARGETSTARTDATETIME DATETIME = NULL
,@INTERVALSTOAGGREGATE INT = NULL
,@RETURN BIT
AS
BEGIN
SET NOCOUNT ON

DECLARE
@DATASETID INT
,@AGGREGATIONINTERVALCOUNT INT
,@LASTMIDNIGHTDATETIME DATETIME
,@CURRENTAGGREGATIONSTARTDELAYMINUTES INT
,@CURRENTAGGREGATIONTYPEID TINYINT
,@CURRENTAGGREGATIONINTERVALDURATIONMINUTES INT
,@INTERVALSTARTDATETIME DATETIME
,@INTERVALENDDATETIME DATETIME
,@DATASETAGGREGATIONHISTORYID INT
,@I INT
,@AGGREGATIONSTARTDATETIME DATETIME
,@STATEMENT NVARCHAR(255)
,@UTCOFFSETMINUTES INT
,@MAXDATAAGEDAYS INT
,@MAXHISTORYDATE DATETIME

DECLARE
@ERROR INT

SET @UTCOFFSETMINUTES = DATEDIFF(MINUTE, GETDATE(), GETUTCDATE())

SELECT
@DATASETID = DATASETID,
@AGGREGATIONINTERVALCOUNT = ISNULL(@INTERVALSTOAGGREGATE, DEFAULTAGGREGATIONINTERVALCOUNT),
@CURRENTAGGREGATIONTYPEID = AGTYPE.AGGREGATIONTYPEID,
@CURRENTAGGREGATIONINTERVALDURATIONMINUTES = AGTYPE.AGGREGATIONINTERVALDURATIONMINUTES,
@CURRENTAGGREGATIONSTARTDELAYMINUTES = AGTYPE.AGGREGATIONSTARTDELAYMINUTES,
@STATEMENT = AGGREGATIONMETHODNAME
FROM APM.DATASET DATASET
JOIN APM.AGGREGATIONTYPE AGTYPE ON AGTYPE.AGGREGATIONTYPEID = DATASET.AGGREGATIONTYPEID
WHERE DATASET.DATASETNAME = @DATASETNAME

SET @ERROR = 0

IF (@AGGREGATIONINTERVALCOUNT &lt; 1)
SET @AGGREGATIONINTERVALCOUNT = 1

IF (@AGGREGATIONTARGETSTARTDATETIME IS NULL)
SET @AGGREGATIONTARGETSTARTDATETIME = GETUTCDATE()

-- FIND THE LAST AGGREGATION INTERVAL WHICH ENDED BEFORE
-- THE AGGREGATION START DATE TIME
IF (@CURRENTAGGREGATIONTYPEID &lt; 30)
BEGIN
--HOURLY AGGREGATION
SET @LASTMIDNIGHTDATETIME = CAST(CONVERT(CHAR(8), @AGGREGATIONTARGETSTARTDATETIME, 112) AS DATETIME)
SET @INTERVALSTARTDATETIME = DATEADD(
MINUTE
,ABS(DATEDIFF(MINUTE, @LASTMIDNIGHTDATETIME, @AGGREGATIONTARGETSTARTDATETIME)) / @CURRENTAGGREGATIONINTERVALDURATIONMINUTES * @CURRENTAGGREGATIONINTERVALDURATIONMINUTES - @CURRENTAGGREGATIONINTERVALDURATIONMINUTES
,CAST(CONVERT(CHAR(8), @AGGREGATIONTARGETSTARTDATETIME, 112) AS DATETIME))
END
ELSE IF (@CURRENTAGGREGATIONTYPEID = 30)
BEGIN
--DAILY AGGREGATION
-- SET @INTERVALSTARTDATETIME = DATEADD(MINUTE, @UTCOFFSETMINUTES, CAST(CONVERT(CHAR(8), GETDATE(), 112) AS DATETIME))
SET @INTERVALSTARTDATETIME = DATEADD(MINUTE, @UTCOFFSETMINUTES, CAST(CONVERT(CHAR(8), @AGGREGATIONTARGETSTARTDATETIME, 112) AS DATETIME))
END

SET @I = @AGGREGATIONINTERVALCOUNT

DECLARE @AGGREGATION TABLE
(
AGGREGATIONDATETIME DATETIME NOT NULL,
AGGREGATIONTYPEID BIT NOT NULL
)

WHILE (@I &gt; 0)
BEGIN
INSERT @AGGREGATION(AGGREGATIONDATETIME, AGGREGATIONTYPEID)
VALUES (@INTERVALSTARTDATETIME, @CURRENTAGGREGATIONTYPEID)

SET @I = @I - 1
SET @INTERVALSTARTDATETIME = DATEADD(MINUTE, -@CURRENTAGGREGATIONINTERVALDURATIONMINUTES, @INTERVALSTARTDATETIME)
END

-- GROOM AGGREGATION HISTORY
SELECT @MAXDATAAGEDAYS = ISNULL(MAXDATAAGEDAYS, 30)
FROM DATASET WHERE DATASETID = @DATASETID
SELECT @MAXHISTORYDATE = DATEADD(DD, -@MAXDATAAGEDAYS, ISNULL(MAX(AGGREGATIONDATETIME), GETUTCDATE()))
FROM DATASETAGGREGATIONHISTORY WHERE DIRTYIND = 0 AND DATASETID = @DATASETID

DELETE DATASETAGGREGATIONHISTORY
WHERE (AGGREGATIONDATETIME &lt; @MAXHISTORYDATE) AND (DIRTYIND = 0)

INSERT APM.DATASETAGGREGATIONHISTORY (
DATASETID
,AGGREGATIONDATETIME
)
SELECT
@DATASETID
,A.AGGREGATIONDATETIME
FROM @AGGREGATION A
WHERE NOT EXISTS (SELECT * FROM APM.DATASETAGGREGATIONHISTORY
WHERE (DATASETID = @DATASETID)
AND (AGGREGATIONDATETIME = A.AGGREGATIONDATETIME)
)


-- SELECT AGGREGATION PERIOD TO WORK ON
-- FIRST SELECT OLDEST NEVER AGGREGATED INTERVAL
-- IF NONE EXIST SELECT OLDEST DIRTY INTERVAL
SELECT TOP 1
@DATASETAGGREGATIONHISTORYID = DATASETAGGREGATIONHISTORYID
,@INTERVALSTARTDATETIME = AH.AGGREGATIONDATETIME
,@INTERVALENDDATETIME = DATEADD(MINUTE, @CURRENTAGGREGATIONINTERVALDURATIONMINUTES, AH.AGGREGATIONDATETIME)
FROM APM.DATASETAGGREGATIONHISTORY AH
WHERE (AH.DATASETID = @DATASETID)
AND (DATEADD(MINUTE, @CURRENTAGGREGATIONINTERVALDURATIONMINUTES + @CURRENTAGGREGATIONSTARTDELAYMINUTES, AH.AGGREGATIONDATETIME) &lt; GETUTCDATE()) -- AGGREGATION INTERVAL + SLIGHT DELAY IS IN THE PAST
AND (DIRTYIND = 1)
ORDER BY AH.AGGREGATIONDATETIME ASC

IF (@RETURN = 1)
BEGIN
CREATE TABLE #DATASETAGGREGATETABLE
(
UTCDATE DATETIME
,PCTYPEID INT
,MACHINEID INT
,SOURCEID INT
,PCPROCESSID INT
,IS_STATE INT
,AVERAGEVALUE DECIMAL(18, 4)
,SUMVALUE DECIMAL(18, 4)
,MINVALUE DECIMAL(18, 4)
,MAXVALUE DECIMAL(18, 4)
,SAMPLECOUNT INT
,PACKAGECOUNTER INT
)
SET @ERROR = @@ERROR

IF (@ERROR &lt;&gt; 0)
GOTO ERRORQUIT
END

IF (@DATASETAGGREGATIONHISTORYID IS NOT NULL)
BEGIN
DECLARE @SQL NVARCHAR(1000)
SET @SQL =
N'EXEC APM.' + QUOTENAME(@STATEMENT) +
'
@DESCRIPTORS
,@INTERVALSTARTDATETIME
,@INTERVALENDDATETIME
'
IF (@RETURN = 1)
SET @SQL = N'INSERT INTO #DATASETAGGREGATETABLE ' + @SQL

EXECUTE SP_EXECUTESQL @SQL, N'@DESCRIPTORS ntext, @INTERVALSTARTDATETIME datetime, @INTERVALENDDATETIME datetime',
@DESCRIPTORS,
@INTERVALSTARTDATETIME,
@INTERVALENDDATETIME

SET @ERROR = @@ERROR
IF (@ERROR = 0)
BEGIN
-- UPDATE AGGREGATION HISTORY
UPDATE DATASETAGGREGATIONHISTORY
SET DIRTYIND = 0
WHERE (DATASETID = @DATASETID)
AND (AGGREGATIONDATETIME = @INTERVALSTARTDATETIME)
END
END

IF (@RETURN = 1)
SELECT * FROM #DATASETAGGREGATETABLE

ERRORQUIT:
RETURN @ERROR
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.PCOUNTERAGGREGATE'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.PCOUNTERAGGREGATE AS RETURN 1')
END
GO
alter PROCEDURE APM.PCOUNTERAGGREGATE
@DESCRIPTORS NTEXT
,@INTERVALSTARTDATETIME DATETIME
,@INTERVALENDDATETIME DATETIME
AS
BEGIN
SET NOCOUNT ON

DECLARE @ERROR INT

SET @ERROR = 0

CREATE TABLE #PCOUNTERAGGREGATE_TMP (PCTYPEID INT, MACHINEID INT, PACKAGECOUNTER INT)

INSERT INTO #PCOUNTERAGGREGATE_TMP(PCTYPEID, MACHINEID, PACKAGECOUNTER)

SELECT
P.PCTYPEID,
P.MACHINEID,
COUNT(DISTINCT P.UTCDATE) PACKAGE_COUNT
FROM
PERFHOURLY P WITH (NOLOCK)
JOIN PCTYPE T WITH (NOLOCK) ON T.PCTYPEID = P.PCTYPEID AND
T.TYPE IN (
N'\Processor\% Processor Time',
N'\PROCESS\PRIVATE BYTES',
N'\PROCESS\IO DATA BYTES/SEC'
)
WHERE
(COALESCE(P.SUMVALUE, 0) &lt;&gt; 0)
AND (P.UTCDATE &gt;= @INTERVALSTARTDATETIME)
AND (P.UTCDATE &lt; @INTERVALENDDATETIME)
GROUP BY
P.PCTYPEID,
P.MACHINEID

INSERT PERFDAILY (
UTCDATE
,PCTYPEID
,MACHINEID
,SOURCEID
,PCPROCESSID
,IS_STATE
,AVERAGEVALUE
,SUMVALUE
,MINVALUE
,MAXVALUE
,SAMPLECOUNT
,PACKAGECOUNTER
)
SELECT
@INTERVALSTARTDATETIME
,P.PCTYPEID
,P.MACHINEID
,P.SOURCEID
,P.PCPROCESSID
,P.IS_STATE
,AVG(P.SUMVALUE)
,SUM(P.SUMVALUE)
,MIN(P.SUMVALUE)
,MAX(P.SUMVALUE)
,COUNT(*)
,MIN(PACK.PACKAGECOUNTER)
FROM
APM.PERFHOURLY P
JOIN #PCOUNTERAGGREGATE_TMP PACK ON PACK.MACHINEID = P.MACHINEID AND PACK.PCTYPEID = P.PCTYPEID
WHERE
(COALESCE(P.SUMVALUE, 0) &lt;&gt; 0)
AND (P.UTCDATE &gt;= @INTERVALSTARTDATETIME)
AND (P.UTCDATE &lt; @INTERVALENDDATETIME)
GROUP BY
P.PCTYPEID
,P.MACHINEID
,P.SOURCEID
,P.PCPROCESSID
,P.IS_STATE

QUIT:
QUITERROR:
RETURN @ERROR
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.RUNDAILYAGGREGATEOPERATION'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.RUNDAILYAGGREGATEOPERATION AS RETURN 1')
END
GO

ALTER PROCEDURE APM.RUNDAILYAGGREGATEOPERATION
@DATASETNAME NVARCHAR(50)
,@DESCRIPTORS NTEXT
,@AGGREGATIONTARGETSTOPDATETIME DATETIME
,@TRACELEVEL INT
AS
BEGIN
SET NOCOUNT ON

DECLARE
@ERROR INT
,@STARTDATE DATETIME
,@ENDDATE DATETIME
,@STEPCOUNT INT
,@MAXDAILYDATAAGEDAYS INT
,@MAXHOURLYDATAAGEDAYS INT
,@MAXDAILYHISTORYDATE DATETIME
,@MAXHOURLYHISTORYDATE DATETIME
,@UTCOFFSETMINUTES INT
,@UTCDATETIME DATETIME
,@CHECKDATE DATETIME
,@HANDLER INT
,@ROWCOUNT INT
,@RESLOCK BIT

SET @RESLOCK = 0
EXECUTE @ERROR = SP_GETAPPLOCK
@RESOURCE = N'RUNDAILYAGGREGATEOPERATION'
,@LOCKMODE = N'Exclusive'
,@LOCKOWNER = N'Session'
,@LOCKTIMEOUT = '0'

IF @ERROR = 0
SET @RESLOCK = 1
IF @ERROR &lt;&gt; 0
BEGIN
IF @ERROR = -1 SET @ERROR = 0
GOTO QUIT
END

SET @ERROR = 0

SET @UTCOFFSETMINUTES = DATEDIFF(MINUTE, GETDATE(), GETUTCDATE())

SELECT
@ENDDATE = MAX(UTCDATE)
FROM
PERFHOURLY WITH (NOLOCK)
WHERE
UTCDATE &lt; @AGGREGATIONTARGETSTOPDATETIME
SET @ENDDATE = ISNULL(@ENDDATE, '19010101')

SET @UTCDATETIME = DATEADD(MINUTE, @UTCOFFSETMINUTES, CAST(CONVERT(CHAR(8), @ENDDATE, 112) AS DATETIME))
SET @ENDDATE = DATEADD(HH,DATEPART(HH, @UTCDATETIME), CAST(CONVERT(CHAR(8), @ENDDATE, 112) AS DATETIME))

SELECT @STARTDATE = MAX(H.AGGREGATIONDATETIME)
FROM APM.DATASETAGGREGATIONHISTORY H
JOIN DATASET D ON D.DATASETID = H.DATASETID AND D.DATASETNAME = @DATASETNAME
WHERE H.DIRTYIND = 0

IF @STARTDATE IS NULL
BEGIN
SELECT @STARTDATE = MIN(UTCDATE)
FROM PERFHOURLY WITH (NOLOCK)
WHERE UTCDATE &lt; @AGGREGATIONTARGETSTOPDATETIME
END
SET @STARTDATE = ISNULL(@STARTDATE, '19010101')

SET @STARTDATE = DATEADD(DD, -1, @STARTDATE)
SET @STEPCOUNT = ISNULL(DATEDIFF(DD, @STARTDATE, @ENDDATE), 0)

SET @CHECKDATE = DATEADD(HH,DATEPART(HH, @UTCDATETIME), CAST(CONVERT(CHAR(8), @STARTDATE, 112) AS DATETIME))

WHILE (DATEADD(DD, @STEPCOUNT + 1, @CHECKDATE) &gt; @ENDDATE)
BEGIN
SET @STEPCOUNT = @STEPCOUNT - 1
END
SET @ENDDATE = DATEADD(DD, -1, @ENDDATE)

IF (@STEPCOUNT &gt; 0)
BEGIN
EXEC APM.DATASETAGGREGATE
@DATASETNAME
,@DESCRIPTORS
,@AGGREGATIONTARGETSTARTDATETIME = @ENDDATE
,@INTERVALSTOAGGREGATE = @STEPCOUNT
,@RETURN = 0

SET @ERROR = @@ERROR

IF (@ERROR &lt;&gt; 0)
GOTO QUIT

SET @STEPCOUNT = @STEPCOUNT - 1
END

WHILE (@STEPCOUNT &gt; 0)
BEGIN
EXEC APM.DATASETAGGREGATE
@DATASETNAME
,@DESCRIPTORS
,@AGGREGATIONTARGETSTARTDATETIME = @ENDDATE
,@INTERVALSTOAGGREGATE = 1
,@RETURN = 0

IF (@ERROR &lt;&gt; 0)
GOTO QUIT

SET @STEPCOUNT = @STEPCOUNT - 1
END

SET @ERROR = @@ERROR

QUIT:
IF @RESLOCK = 1
BEGIN
EXECUTE SP_RELEASEAPPLOCK
@RESOURCE = N'RUNDAILYAGGREGATEOPERATION'
,@LOCKOWNER = N'Session'
END
RETURN @ERROR
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.HourlyTableInit'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.HourlyTableInit AS RETURN 1')
END
GO

alter procedure APM.HourlyTableInit
as
begin
declare
@DATE as datetime
,@ITERATOR as int

set @ITERATOR = 1
set @DATE = '19000101'
while @ITERATOR &lt;= 24
begin
insert into APM.HourlyTable Values(@DATE)
set @DATE = dateadd(hh, 1, @DATE)
set @ITERATOR = @ITERATOR + 1
end
end
GO

exec APM.HourlyTableInit
GO

drop procedure APM.HourlyTableInit
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.DISABLE_FOREIGN_KEYS'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.DISABLE_FOREIGN_KEYS AS RETURN 1')
END
GO
ALTER PROCEDURE APM.DISABLE_FOREIGN_KEYS
@DISABLE BIT = 1
AS
BEGIN

DECLARE
@SQL NVARCHAR(500),
@TABLENAME NVARCHAR(128),
@FOREIGNKEYNAME NVARCHAR(128)

-- A LIST OF ALL OF THE FOREIGN KEYS AND THE TABLE NAMES
DECLARE FOREIGNKEYCURSOR CURSOR
FOR
SELECT
REF.CONSTRAINT_NAME AS FK_NAME,
FK.TABLE_NAME AS FK_TABLE
FROM
INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS REF
INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS FK ON REF.CONSTRAINT_NAME = FK.CONSTRAINT_NAME
ORDER BY
FK.TABLE_NAME,
REF.CONSTRAINT_NAME

OPEN FOREIGNKEYCURSOR

FETCH NEXT FROM FOREIGNKEYCURSOR INTO @FOREIGNKEYNAME, @TABLENAME
WHILE ( @@FETCH_STATUS = 0 )
BEGIN
IF @DISABLE = 1
SET @SQL = N'ALTER TABLE [' + @TABLENAME + N'] NOCHECK CONSTRAINT [' + @FOREIGNKEYNAME + ']'
ELSE
SET @SQL = N'ALTER TABLE [' + @TABLENAME + N'] CHECK CONSTRAINT [' + @FOREIGNKEYNAME + ']'
PRINT 'EXECUTING STATEMENT - ' + @SQL
EXECUTE(@SQL)
FETCH NEXT FROM FOREIGNKEYCURSOR INTO @FOREIGNKEYNAME, @TABLENAME
END

CLOSE FOREIGNKEYCURSOR

DEALLOCATE FOREIGNKEYCURSOR

END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.SHOWMESSAGE'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.SHOWMESSAGE AS RETURN 1')
END
GO

ALTER PROCEDURE APM.SHOWMESSAGE @MESSAGE NVARCHAR(100) AS
BEGIN
RAISERROR (@MESSAGE, 0, 1) WITH NOWAIT
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.FILLGROUPS'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.FILLGROUPS AS RETURN 1')
END
GO
/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: FILLGROUPS */
/* DESCRIPTION: The procedure create resource group node only for the */
/* performance events. It will be called only if rowdata contains */
/* resource group section. */
/* INPUT PARAMETERS: */
/* @ROWGUID - unique identifier of the event record */
/* @GROUPSDOC - xml resource group package for processing */
/* &lt;callGroups&gt; */
/* &lt;callGroup name="{resource group}" */
/* duration="{duration,ms}" */
/* count="{call count}" /&gt; */
/* ... */
/* &lt;callGroup/&gt; */
/* &lt;/callGroups&gt; */
/* @TRACELEVEL - trace level */
/************************************************************************************/
ALTER PROCEDURE APM.FILLGROUPS
@ROWGUID NVARCHAR(15)
,@GROUPSDOC NTEXT
,@TRACELEVEL INT
AS
BEGIN
SET NOCOUNT ON

-- temporary table. Possible it is need to reseach using temporary variable ---
CREATE TABLE #GROUPS (NAME NVARCHAR(255) collate database_default, CALLCOUNT INT, DURATION BIGINT)

-- memory identifier
DECLARE @IDOC INT

-- error code
DECLARE @ERR INT

-- primary key for the @ROWGUID parameter
DECLARE @EVENTID BIGINT

-- row affected records
DECLARE @ROWAFFECTED AS INT

-- temporary variable for row affected records
DECLARE @RECORDCOUNT INT

-- error proccesing
DECLARE
@ERRORIND bit
,@ERRORNUMBER int
,@ERRORSEVERITY int
,@ERRORSTATE int
,@ERRORLINE int
,@ERRORPROCEDURE nvarchar(256)
,@ERRORMESSAGETEXT nvarchar(max)
,@ERROR_MESSAGE nvarchar(max)
,@MESSAGE nvarchar(max)

-- reset error flag
SET @ERRORIND = 0

BEGIN TRY

-- get event primary key using idx_T_RowGuid
SELECT @EVENTID = EventId FROM Event e(NOLOCK) WHERE e.rowGuid = @ROWGUID

IF (@@ROWCOUNT = 0)
BEGIN
-- raise exception "{rowguid} not found"
SELECT @ERROR_MESSAGE = message FROM APM.messages WHERE id = 50006
RAISERROR(@ERROR_MESSAGE, 16, 1, 'FILLGROUPS', @ROWGUID)
END

-- allocate memory for xml processing
EXEC @ERR = SP_XML_PREPAREDOCUMENT @IDOC OUTPUT, @GROUPSDOC
IF @ERR &lt;&gt; 0
BEGIN
-- raise exception
SELECT @ERROR_MESSAGE = message FROM APM.messages WHERE id = 50002
RAISERROR(@ERROR_MESSAGE, 16, 1, 'FILLGROUPS', @ERR)
END

-- Parse xml package
INSERT INTO #GROUPS
SELECT NAME, CALLCOUNT, DURATION
FROM OPENXML(@IDOC, N'/callGroups/callGroup', 2)
WITH (NAME NVARCHAR(255) N'@name', CALLCOUNT INT N'@count', DURATION BIGINT N'@duration')

SELECT @ROWAFFECTED = @@ROWCOUNT

-- free memory
EXEC SP_XML_REMOVEDOCUMENT @IDOC

SET @IDOC = NULL

IF (@TRACELEVEL = 4 AND @ROWAFFECTED = 0)
BEGIN
-- trace message
SELECT @MESSAGE = message FROM APM.Messages WHERE ID = 50007
RAISERROR (@MESSAGE, 0, 1) WITH NOWAIT;
END

-- if resource group exists
IF @ROWAFFECTED &gt; 0
BEGIN
-- create resource group
INSERT INTO APM.RESOURCEGROUP (NAME)
SELECT DISTINCT APM.GETRESOURCETYPE(G.NAME) FROM #GROUPS G
WHERE NOT EXISTS
(
SELECT * FROM RESOURCEGROUP RG (NOLOCK) WHERE RG.NAME = APM.GETRESOURCETYPE(G.NAME)
)

SELECT @RECORDCOUNT = @@ROWCOUNT
IF (@TRACELEVEL = 4)
BEGIN
-- trace message
SELECT @MESSAGE = message FROM APM.Messages WHERE ID = 50008
RAISERROR (@MESSAGE, 0, 1, @RECORDCOUNT) WITH NOWAIT;
END

-- Check exitsing internal resource group. It is need to create.
IF NOT EXISTS(SELECT * FROM RESOURCEGROUP RG (NOLOCK) WHERE RG.NAME = N'Internal')
INSERT INTO RESOURCEGROUP(NAME) VALUES (N'Internal')

-- create resource group node for all resourtce calls
;WITH RESOURCEGROUPNODESET(EVENTID, DURATION, CALLCOUNT, RESOURCEGROUPID) AS
(
-- by resource group calls from package
SELECT
@EVENTID EVENTID,
SUM(G.DURATION) DURATION,
SUM(G.CALLCOUNT) CALLCOUNT,
RG.RESOURCEGROUPID
FROM
#GROUPS G
JOIN
RESOURCEGROUP RG (NOLOCK) ON RG.NAME = APM.GETRESOURCETYPE(G.NAME)
GROUP BY
RG.RESOURCEGROUPID

UNION ALL

-- calculate internal call group as
SELECT
EVENTID, DURATION, CALLCOUNT, RESOURCEGROUPID
FROM
(
SELECT
@EVENTID EVENTID,
-- Rule: event duration - all resource group call
COALESCE(E.EVENTDURATION, 0) / 1000 - COALESCE(A.DURATION, 0) DURATION,
NULL CALLCOUNT,
(SELECT RESOURCEGROUPID FROM RESOURCEGROUP RG WHERE RG.NAME = N'Internal') RESOURCEGROUPID
FROM
EVENT E (NOLOCK)
CROSS JOIN
(
SELECT
SUM(G.DURATION) DURATION
FROM
#GROUPS G
) A
WHERE
E.EVENTID = @EVENTID
) B
WHERE B.DURATION &gt; 0
),
-- grouping result by resource group
RESOURCEGROUPNODESETUNIQ(EVENTID, DURATION, CALLCOUNT, RESOURCEGROUPID) AS
(
SELECT
@EVENTID, SUM(DURATION), SUM(CALLCOUNT), RESOURCEGROUPID
FROM
RESOURCEGROUPNODESET
GROUP BY
RESOURCEGROUPID
)
-- create resource group node
INSERT INTO RESOURCEGROUPNODE(EVENTID, DURATION, CALLCOUNT, RESOURCEGROUPID)
SELECT
EVENTID, DURATION, CALLCOUNT, RESOURCEGROUPID
FROM
RESOURCEGROUPNODESETUNIQ

SELECT @RECORDCOUNT = @@ROWCOUNT
IF (@TRACELEVEL = 4)
BEGIN
-- trace level
SELECT @MESSAGE = message FROM APM.Messages WHERE ID = 50010
RAISERROR (@MESSAGE, 0, 1, @RECORDCOUNT) WITH NOWAIT;
END
END
END TRY
BEGIN CATCH
-- exception processing

-- check active transactions
IF (@@TRANCOUNT &gt; 0)
ROLLBACK TRAN

-- get context variables
SELECT
@ERRORNUMBER = ERROR_NUMBER()
,@ERRORSEVERITY = ERROR_SEVERITY()
,@ERRORSTATE = ERROR_STATE()
,@ERRORLINE = ERROR_LINE()
,@ERRORPROCEDURE = ISNULL(ERROR_PROCEDURE(), '-')
,@ERRORMESSAGETEXT = ERROR_MESSAGE()

-- switch error flag
SET @ERRORIND = 1
END CATCH
-- check memory handle
IF @IDOC IS NOT NULL
EXEC sp_xml_removedocument @IDOC

-- report error if any
IF (@ERRORIND = 1)
BEGIN
DECLARE @ADJUSTEDERRORSEVERITY int

SET @ADJUSTEDERRORSEVERITY = CASE
WHEN @ERRORSEVERITY &gt; 18 THEN 18
ELSE @ERRORSEVERITY
END

SELECT @ERROR_MESSAGE = message FROM APM.Messages WHERE id = 50004
RAISERROR (@ERROR_MESSAGE, @ADJUSTEDERRORSEVERITY, 1
,@ERRORNUMBER
,@ERRORSEVERITY
,@ERRORSTATE
,@ERRORPROCEDURE
,@ERRORLINE
,@ERRORMESSAGETEXT
)
END
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.FillResourceGroupNodes'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.FillResourceGroupNodes AS RETURN 1')
END
GO
/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: FillResourceGroupNodes */
/* DESCRIPTION: The procedure create resource group node for the performance nodes */
/* This is internal stored procedure. It is used by FillResource */
/* stored procedure. The FillResourceGroupNodes use external */
/* temporary table. Existing resource group node is not check. */
/* INPUT PARAMETERS: */
/* @EVENTID - primary key of the event record */
/* @TRACELEVEL - trace level */
/************************************************************************************/
ALTER PROCEDURE APM.FillResourceGroupNodes
@EVENTID bigint
,@TRACELEVEL int
AS
BEGIN
SET NOCOUNT ON;

DECLARE
@MESSAGE nvarchar(max)
,@RECORDCOUNT int

IF @TRACELEVEL = 4
BEGIN
-- trace message
SELECT @MESSAGE = MESSAGE FROM APM.MESSAGES WHERE ID = 50031
RAISERROR (@MESSAGE, 0, 1) WITH NOWAIT;
END

;WITH ResourceGroupNodeSet(DURATION, RESOURCEGROUPID) AS
(
-- grouping resources from xml resource package
SELECT
SUM(D.DUR) DURATION,
D.RESOURCEGROUPID
FROM
#DETAILS D
GROUP BY
D.RESOURCEGROUPID

UNION ALL

-- calculate one internal execution. Internal resource group should be create before.
SELECT
DURATION, RESOURCEGROUPID
FROM
(
SELECT
-- calculation rule: event duration - all resource call group duration
COALESCE(A.EVENTDURATION, 0) / 1000 - COALESCE(A.DURATION, 0) DURATION,
RG.RESOURCEGROUPID
FROM
RESOURCEGROUP RG (NOLOCK)
CROSS JOIN
(
-- all resource call group duration
SELECT
SUM(D.DUR) DURATION
,MIN(D.EVENTDURATION) EVENTDURATION
FROM
#DETAILS D
) A
WHERE
RG.NAME = N'Internal'
) B
WHERE B.DURATION &gt; 0
),
-- grouping by resource group
ResourceGroupNodeSetUniq(EVENTID, DURATION, CALLCOUNT, RESOURCEGROUPID) AS
(
SELECT
@EVENTID, SUM(DURATION), NULL, RESOURCEGROUPID
FROM
ResourceGroupNodeSet
GROUP BY
RESOURCEGROUPID
)
INSERT INTO RESOURCEGROUPNODE(EVENTID, DURATION, CALLCOUNT, RESOURCEGROUPID)
SELECT
EVENTID, DURATION, CALLCOUNT, RESOURCEGROUPID
FROM
ResourceGroupNodeSetUniq

SELECT @RECORDCOUNT = @@ROWCOUNT

IF @TRACELEVEL = 4
BEGIN
-- trace level
SELECT @MESSAGE = MESSAGE FROM APM.MESSAGES WHERE ID = 50032
RAISERROR (@MESSAGE, 0, 1, N'FILLRESOURCEGROUPNODES', @RECORDCOUNT, N'RESOURCEGROUPNODE') WITH NOWAIT;
END
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.FILLRESOURCES'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.FILLRESOURCES AS RETURN 1')
END
GO
/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: FILLRESOURCES */
/* DESCRIPTION: The procedure update resource references on the performancenode, */
/* exceptionnode, event tables. If resource doesn't exist it */
/* will be create. If rowdata doesn't contain resource group call */
/* section resource group node will be create on the */
/* resourcegroupnode table for the performance events. */
/* INPUT PARAMETERS: */
/* @ROWGUID - unique identifier of the event record */
/* @DETAILSDOC - xml resource package for processing */
/* &lt;resources&gt; */
/* &lt;resource entryId="{entry id}" quick="{0(1)}"&gt; */
/* &lt;method dur="{duration, ms}"&gt;{method name}&lt;/method&gt; */
/* &lt;uriFormat&gt;{uri format}&lt;/uriFormat&gt; */
/* &lt;type&gt;{resource type}&lt;/type&gt; */
/* &lt;/resource&gt; */
/* ... */
/* &lt;resource/&gt; */
/* &lt;/resources&gt; */
/* quick attribute values: */
/* 1 quick resource call */
/* 0 not quick resource call */
/* resource method format: */
/* {namespace}${resource call} */
/* {uri format} reserved */
/* @TRACELEVEL - trace level */
/************************************************************************************/
ALTER PROCEDURE [APM].[FILLRESOURCES]
@ROWGUID NVARCHAR(15)
,@DETAILSDOC NTEXT
,@TRACELEVEL INT
AS
BEGIN
SET NOCOUNT ON

-- memory identifier
DECLARE @IDOC INT

-- error code
DECLARE @ERR INT
-- event class type
DECLARE @EVENTCLASSTYPE NVARCHAR(255)

-- primary key for the @ROWGUID parameter
DECLARE @EVENTID BIGINT

-- row affected records
DECLARE @ROWAFFECTED AS INT

-- trace message
DECLARE @MESSAGE NVARCHAR(MAX)

-- temporary variable for row affected records
DECLARE @RECORDCOUNT INT

-- error proccesing
DECLARE
@ERRORIND bit
,@ERRORNUMBER int
,@ERRORSEVERITY int
,@ERRORSTATE int
,@ERRORLINE int
,@ERRORPROCEDURE nvarchar(256)
,@ERRORMESSAGETEXT nvarchar(max)
,@ERROR_MESSAGE nvarchar(max)

-- reset error flag
SET @ERRORIND = 0

BEGIN TRY

-- temporary table. Possible it is need to reseach using temporary variable ---
CREATE TABLE #DETAILS (
ENTRYID INT
,METHOD nvarchar(255) collate database_default
,RESOURCEURI nvarchar(255) collate database_default
,URIFORMAT NVARCHAR(255) collate database_default
,TYPE NVARCHAR(255) collate database_default
,QUICK INT
,DUR decimal(35,0)
,RESOURCEGROUPID int
,SOURCEID int
,EVENTID bigint
,EVENTDURATION decimal(35,0)
)

-- get event primary key using idx_T_RowGuid
SELECT @EVENTID = EventId FROM APM.Event e(NOLOCK) WHERE e.rowGuid = @ROWGUID
IF (@@ROWCOUNT = 0)
BEGIN
-- raise exception "{rowguid} not found"
SELECT @ERROR_MESSAGE = message FROM APM.messages WHERE id = 50006
RAISERROR(@ERROR_MESSAGE, 16, 1, 'FILLRESOURCES', @ROWGUID)
END

-- allocate memory for xml processing
EXEC @ERR = SP_XML_PREPAREDOCUMENT @IDOC OUTPUT, @DETAILSDOC
IF @ERR &lt;&gt; 0
BEGIN
-- raise exception
SELECT @ERROR_MESSAGE = message FROM APM.messages WHERE id = 50002
RAISERROR(@ERROR_MESSAGE, 16, 1, 'FILLRESOURCES', @ERR)
END

-- Parse xml package
INSERT INTO #DETAILS
SELECT ENTRYID, METHOD, APM.GETRESOURCE(METHOD), URIFORMAT, TYPE, QUICK, DUR, 0, 0, 0, 0
FROM OPENXML(@IDOC, N'/resources/resource', 2)
WITH (
ENTRYID INT N'@entryId',
METHOD NVARCHAR(255) N'method',
URIFORMAT NVARCHAR(255) N'uriFormat',
TYPE NVARCHAR(255) N'type',
QUICK INT N'@quick',
DUR decimal(35,0) N'method/@dur'
)
SELECT @ROWAFFECTED = @@ROWCOUNT

-- free memory
EXEC SP_XML_REMOVEDOCUMENT @IDOC

SET @IDOC = NULL

IF @TRACELEVEL = 4 AND @ROWAFFECTED = 0
BEGIN
-- resources is empty
SELECT @MESSAGE = MESSAGE FROM APM.MESSAGES WHERE ID = 50013
RAISERROR (@MESSAGE, 0, 1) WITH NOWAIT;
END

-- if resources exists
IF @ROWAFFECTED &gt; 0
BEGIN

-- get event class type using index idx_T_EventId
SELECT
@EVENTCLASSTYPE = EVENTCLASSTYPE
FROM
APM.EVENT E (NOLOCK)
WHERE
E.EVENTID = @EVENTID

-- create resource group
INSERT INTO APM.RESOURCEGROUP (NAME)
SELECT DISTINCT APM.GETRESOURCETYPE(D.TYPE) FROM #DETAILS D
WHERE NOT EXISTS
(
SELECT * FROM APM.RESOURCEGROUP RG (NOLOCK) WHERE RG.NAME = APM.GETRESOURCETYPE(D.TYPE)
)

-- updating additional fields. It is need for decrease number of join operations.
UPDATE D
SET
D.RESOURCEGROUPID = RG.RESOURCEGROUPID
,D.SOURCEID = E.SOURCEID
,D.EVENTID = E.EVENTID
,D.EVENTDURATION = E.EVENTDURATION
FROM #DETAILS D
JOIN RESOURCEGROUP RG (NOLOCK) ON RG.NAME = APM.GETRESOURCETYPE(D.TYPE)
CROSS JOIN (SELECT EVENTID, SOURCEID, EVENTDURATION FROM APM.EVENT E (NOLOCK) WHERE E.EVENTID = @EVENTID) E

-- Check exitsing internal resource group. It is need to create.
IF NOT EXISTS(SELECT * FROM APM.RESOURCEGROUP RG (NOLOCK) WHERE RG.NAME = N'Internal')
INSERT INTO RESOURCEGROUP(NAME) VALUES (N'Internal')

-- create resource for all methods
INSERT INTO RESOURCE(
SOURCEID,
RESOURCEGROUPID,
RESOURCEURIFORMAT,
RESOURCEURI
)
SELECT
DISTINCT D.SOURCEID, D.RESOURCEGROUPID, D.URIFORMAT, D.RESOURCEURI
FROM
#DETAILS D
WHERE
NOT EXISTS(
SELECT *
FROM
APM.RESOURCE R (NOLOCK)
WHERE
R.SOURCEID = D.SOURCEID
AND R.RESOURCEGROUPID = D.RESOURCEGROUPID
AND R.RESOURCEURI = D.RESOURCEURI
)

SELECT @RECORDCOUNT = @@ROWCOUNT

IF @TRACELEVEL = 4
BEGIN
-- send info message about resource row affected
SELECT @MESSAGE = MESSAGE FROM APM.MESSAGES WHERE ID = 50014
RAISERROR (@MESSAGE, 0, 1, @RECORDCOUNT) WITH NOWAIT;
END

IF @EVENTCLASSTYPE = N'performance' AND EXISTS (SELECT * FROM #DETAILS WHERE QUICK = 0)
BEGIN
-- processing performance events for not quick resource calls
IF @TRACELEVEL = 4
BEGIN
-- trace info message
SELECT @MESSAGE = MESSAGE FROM APM.MESSAGES WHERE ID = 50015
RAISERROR (@MESSAGE, 0, 1) WITH NOWAIT;
END

-- Create resource group node if rowdata doesn't containt resource call group section or it is empty
IF NOT EXISTS(SELECT * FROM RESOURCEGROUPNODE RN WHERE RN.EventId = @EVENTID)
EXEC APM.FillResourceGroupNodes @EVENTID, @TRACELEVEL

--Check existing performance node
IF NOT EXISTS(SELECT * FROM APM.PERFORMANCENODE P (NOLOCK) WHERE P.EVENTID = @EVENTID)
BEGIN
-- It is need create performance node(s) for not quick resource call
IF @TRACELEVEL = 4
BEGIN
-- trace message
SELECT @MESSAGE = MESSAGE FROM APM.MESSAGES WHERE ID = 50016
RAISERROR (@MESSAGE, 0, 1) WITH NOWAIT;
END

INSERT INTO APM.PERFORMANCENODE
(
EVENTID,
DESCRIPTION,
FUNCTIONNAME,
ENTRYID,
DURATION,
SELFDURATION,
ISHEAVIESTNODE
)
SELECT
@EVENTID,
REPLACE(D.METHOD,'$',''),
REPLACE(D.METHOD,'$',''),
D.ENTRYID,
D.DUR,
D.DUR,
1
FROM
#DETAILS D
WHERE
D.QUICK = 0

SELECT @RECORDCOUNT = @@ROWCOUNT

IF @TRACELEVEL = 4
BEGIN
-- trace info message
SELECT @MESSAGE = MESSAGE FROM APM.MESSAGES WHERE ID = 50017
RAISERROR (@MESSAGE, 0, 1, @RECORDCOUNT) WITH NOWAIT;
END
END
-- update resource, resource group node references and resource method for not quick resource calls
UPDATE P SET
P.RESOURCEID = R.RESOURCEID,
P.RESOURCEGROUPNODEID = RGN.RESOURCEGROUPNODEID,
P.RESOURCEMETHOD = REPLACE(D.METHOD, N'$', N''), -- full method name (namespace + resource function call)
P.SELFDURATION = D.DUR
FROM
PERFORMANCENODE P
JOIN #DETAILS D ON D.ENTRYID = P.ENTRYID AND D.QUICK = 0
JOIN RESOURCEGROUPNODE RGN (NOLOCK) ON RGN.RESOURCEGROUPID = D.RESOURCEGROUPID AND RGN.EVENTID = D.EVENTID
JOIN RESOURCE R (NOLOCK) ON R.RESOURCEURI = D.RESOURCEURI AND R.SOURCEID = D.SOURCEID AND R.RESOURCEGROUPID = D.RESOURCEGROUPID
WHERE
P.EVENTID = @EVENTID

SELECT @RECORDCOUNT = @@ROWCOUNT
IF @TRACELEVEL = 4
BEGIN
-- trace message
SELECT @MESSAGE = MESSAGE FROM APM.MESSAGES WHERE ID = 50018
RAISERROR (@MESSAGE, 0, 1, @RECORDCOUNT) WITH NOWAIT;
END
-- update event resource reference. It will be reference to the most heavy resources
UPDATE E SET
E.RESOURCEID = (
SELECT TOP 1
P.RESOURCEID
FROM
PERFORMANCENODE P (NOLOCK)
WHERE
P.EVENTID = @EVENTID
ORDER BY
P.SELFDURATION DESC, P.PERFORMANCENODEID DESC
)
FROM
APM.EVENT E
WHERE
E.EVENTID = @EVENTID

SELECT @RECORDCOUNT = @@ROWCOUNT
IF @TRACELEVEL = 4
BEGIN
-- trace message
SELECT @MESSAGE = MESSAGE FROM APM.MESSAGES WHERE ID = 50020
RAISERROR (@MESSAGE, 0, 1, @RECORDCOUNT) WITH NOWAIT;
END
END

IF @EVENTCLASSTYPE = N'exception' AND EXISTS(SELECT * FROM APM.EXCEPTIONNODE EX (NOLOCK) WHERE EX.EVENTID = @EVENTID)
BEGIN
-- processing exception event

-- update resource reference and resource method
UPDATE EX SET
EX.RESOURCEID = R.RESOURCEID,
EX.RESOURCEMETHOD = REPLACE(D.METHOD, N'$', N'') -- full method name (namespace + resource function call)
FROM APM.EXCEPTIONNODE EX
CROSS JOIN (SELECT METHOD, SOURCEID, RESOURCEURI,RESOURCEGROUPID FROM #DETAILS D WHERE QUICK = 0) D
JOIN APM.RESOURCE R (NOLOCK) ON R.RESOURCEURI = D.RESOURCEURI AND R.SOURCEID = D.SOURCEID AND R.RESOURCEGROUPID = D.RESOURCEGROUPID
WHERE
EX.EVENTID = @EVENTID

SELECT @RECORDCOUNT = @@ROWCOUNT
IF @TRACELEVEL = 4
BEGIN
-- trace info message
SELECT @MESSAGE = MESSAGE FROM APM.MESSAGES WHERE ID = 50021
RAISERROR (@MESSAGE, 0, 1, @RECORDCOUNT) WITH NOWAIT;
END

-- update event resource reference.
UPDATE E SET
E.RESOURCEID = (
SELECT TOP 1
EX.RESOURCEID
FROM
APM.EXCEPTIONNODE EX (NOLOCK)
WHERE
EX.EVENTID = @EVENTID
ORDER BY
EX.RESOURCEID
)
FROM
APM.EVENT E
WHERE
E.EVENTID = @EVENTID

SELECT @RECORDCOUNT = @@ROWCOUNT
IF @TRACELEVEL = 4
BEGIN
-- trace info message
SELECT @MESSAGE = MESSAGE FROM APM.MESSAGES WHERE ID = 50022
RAISERROR (@MESSAGE, 0, 1, @RECORDCOUNT) WITH NOWAIT;
END

END
END
END TRY
BEGIN CATCH
-- exception processing

-- check active transactions
IF (@@TRANCOUNT &gt; 0)
ROLLBACK TRAN

-- get context variables
SELECT
@ERRORNUMBER = ERROR_NUMBER()
,@ERRORSEVERITY = ERROR_SEVERITY()
,@ERRORSTATE = ERROR_STATE()
,@ERRORLINE = ERROR_LINE()
,@ERRORPROCEDURE = ISNULL(ERROR_PROCEDURE(), '-')
,@ERRORMESSAGETEXT = ERROR_MESSAGE()

-- switch error flag
SET @ERRORIND = 1
END CATCH

-- check memory handle
IF @IDOC IS NOT NULL
EXEC sp_xml_removedocument @IDOC

--report error if any
IF (@ERRORIND = 1)
BEGIN
DECLARE @ADJUSTEDERRORSEVERITY int

SET @ADJUSTEDERRORSEVERITY = CASE
WHEN @ERRORSEVERITY &gt; 18 THEN 18
ELSE @ERRORSEVERITY
END

SELECT @ERROR_MESSAGE = message FROM APM.Messages WHERE id = 50004
RAISERROR (@ERROR_MESSAGE, @ADJUSTEDERRORSEVERITY, 1
,@ERRORNUMBER
,@ERRORSEVERITY
,@ERRORSTATE
,@ERRORPROCEDURE
,@ERRORLINE
,@ERRORMESSAGETEXT
)
END
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.UpdateEventsByInternalResource'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.UpdateEventsByInternalResource AS RETURN 1')
END
GO
/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: UpdateEventsByInternalResource */
/* DESCRIPTION: The procedure update resource reference for events */
/* This is internal stored procedure. It is used by FillResource */
/* stored procedure. The UpdateEventsByInternalResource use external */
/* temporary table. */
/* INPUT PARAMETERS: */
/* @EVENTCLASSTYPE - event class type */
/* @TRACELEVEL - trace level */
/************************************************************************************/
ALTER PROCEDURE APM.UpdateEventsByInternalResource @EVENTCLASSTYPE nvarchar(255)
AS
BEGIN
if (@EVENTCLASSTYPE = N'performance')
begin
-- processing performance events
UPDATE E
SET E.RESOURCEID = A.RESOURCEID
FROM
APM.EVENT E
JOIN #FILLINTERNALRESOURCESTABLE F ON F.EVENTID = E.EVENTID
CROSS APPLY (
-- using haviest resource
SELECT TOP 1
P.RESOURCEID
FROM
APM.PERFORMANCENODE P (NOLOCK)
WHERE
P.EVENTID = E.EVENTID
ORDER BY
P.SELFDURATION DESC,
P.PERFORMANCENODEID
) A
end
if @EVENTCLASSTYPE = N'exception'
begin
-- processing exception events
UPDATE E
SET E.RESOURCEID = A.RESOURCEID
FROM
APM.EVENT E
JOIN #FILLINTERNALRESOURCESTABLE F ON F.EVENTID = E.EVENTID
CROSS APPLY (
SELECT TOP 1
EX.RESOURCEID
FROM
APM.EXCEPTIONNODE EX (NOLOCK)
WHERE
EX.EVENTID = E.EVENTID
ORDER BY
EX.EXCEPTIONNODEID
) A
end
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.INSERTINTERNALRESOURCE'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.INSERTINTERNALRESOURCE AS RETURN 1')
END
GO
/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: INSERTINTERNALRESOURCE */
/* DESCRIPTION: The procedure create internal execution resource. */
/* This is internal stored procedure. It is used by */
/* FillInternalResource stored procedure and use external temporary */
/* table. */
/************************************************************************************/
ALTER PROCEDURE APM.INSERTINTERNALRESOURCE
AS
BEGIN
DECLARE @INTERNALRESOURCEGROUPID int

SELECT
-- get primary key for internal resource group
@INTERNALRESOURCEGROUPID = RESOURCEGROUPID FROM APM.RESOURCEGROUP RG WHERE RG.NAME = N'Internal'

-- create internal execution resource for temporary sources
INSERT INTO RESOURCE (RESOURCEGROUPID, SOURCEID, RESOURCEURI, RESOURCEURIFORMAT)
SELECT DISTINCT
@INTERNALRESOURCEGROUPID
,F.SOURCEID
,N'Internal Execution'
,N''
FROM
#FILLINTERNALRESOURCESTABLE F
WHERE
NOT EXISTS(
SELECT *
FROM APM.RESOURCE R (NOLOCK)
WHERE
R.SOURCEID = F.SOURCEID
AND R.RESOURCEURI = N'Internal Execution'
)
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.FILLINTERNALRESOURCES'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.FILLINTERNALRESOURCES AS RETURN 1')
END
GO
/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: FILLINTERNALRESOURCES */
/* DESCRIPTION: The procedure update resource references on the performancenode, */
/* exceptionnode, event tables which is empty. The new resource */
/* will be internal execution. After execution this procedure "heavy */
/* light" events should be performance or exception nodes. Events will*/
/* process by block starting @STARTROWGUID and ending @ENDROWGUID */
/* */
/* INPUT PARAMETERS: */
/* @STARTROWGUID - start block unique identifier */
/* @ENDBLOCK - end block unique identifier */
/* @DATABASEID - database identifier */
/* @RECORDCOUNT - reserved */
/* @TRACELEVEL - trace level */
/************************************************************************************/
ALTER PROCEDURE APM.FILLINTERNALRESOURCES
@STARTROWGUID NVARCHAR(15)
,@ENDROWGUID NVARCHAR(15)
,@DATABASEID INT
,@RECORDCOUNT INT
,@TRACELEVEL INT
AS
BEGIN
SET NOCOUNT ON

DECLARE @RECORDS INT
DECLARE @MESSAGE NVARCHAR(MAX)

-- error proccesing
DECLARE
@ERRORIND bit
,@ERRORNUMBER int
,@ERRORSEVERITY int
,@ERRORSTATE int
,@ERRORLINE int
,@ERRORPROCEDURE nvarchar(256)
,@ERRORMESSAGETEXT nvarchar(max)
,@ERROR_MESSAGE nvarchar(max)

-- reset error flag
SET @ERRORIND = 0

BEGIN TRY

DECLARE
-- starting primary key
@STARTID bigint
-- ending primary key
,@ENDID bigint
-- internal resource group
,@INTERNALRESOURCEGROUPID int

IF NOT EXISTS(SELECT * FROM APM.RESOURCEGROUP WHERE NAME = N'Internal')
INSERT INTO APM.RESOURCEGROUP(NAME) VALUES (N'Internal')

-- Get primary key internal resource group
SELECT
@INTERNALRESOURCEGROUPID = RESOURCEGROUPID FROM APM.RESOURCEGROUP RG WHERE RG.NAME = N'Internal'

-- Get event primary keys
SELECT
@STARTID = CASE WHEN ROWGUID = @STARTROWGUID THEN eventId ELSE @STARTID END
,@ENDID = CASE WHEN ROWGUID = @ENDROWGUID THEN eventId ELSE @ENDID END
FROM
APM.EVENT (NOLOCK)
WHERE
ROWGUID IN (@STARTROWGUID, @ENDROWGUID)

IF @STARTID IS NULL OR @ENDID IS NULL
BEGIN
DECLARE
@MSG nvarchar(MAX)

SELECT @MSG = message FROM APM.MESSAGES(NOLOCK) WHERE id = 50035
RAISERROR(@MSG, 16, 1, @STARTROWGUID, @ENDROWGUID)
RETURN
END


-- temporary event table. Do not use temporary table variable because table is used by internal stored procedures
CREATE TABLE #FILLINTERNALRESOURCESTABLE
(
EVENTID INT
,SOURCEID INT
,EVENTDURATION DECIMAL(35,0)
,EXCEPTIONCLASS NVARCHAR(255) collate database_default
,DESCRIPTION NVARCHAR(255) collate database_default
)

/* Processing performance events which are not have performance nodes */
INSERT INTO #FILLINTERNALRESOURCESTABLE(EVENTID,EVENTDURATION,SOURCEID)
SELECT
E.EVENTID, E.EVENTDURATION,E.SOURCEID
FROM
APM.EVENT (NOLOCK) E
WHERE
E.SEVIEWERDBID = @DATABASEID
AND E.EVENTID &gt;= @STARTID AND E.EVENTID &lt;= @ENDID
AND (HEAVYLIGHT IS NULL OR HEAVYLIGHT &lt;&gt; 0)
AND NOT EXISTS(SELECT * FROM PERFORMANCENODE P (NOLOCK) WHERE P.EVENTID = E.EVENTID)
AND E.EVENTCLASSTYPE = N'performance' OPTION(RECOMPILE)

IF (@@ROWCOUNT &gt; 0)
BEGIN
-- Processing performance events

-- Delete old resource group nodes
DELETE R FROM
APM.RESOURCEGROUPNODE R
JOIN #FILLINTERNALRESOURCESTABLE F ON F.EVENTID = R.EVENTID

--Insert internal resource group node
INSERT RESOURCEGROUPNODE(EVENTID, DURATION, CALLCOUNT, RESOURCEGROUPID)
SELECT
F.EVENTID,
-- use event duration
COALESCE(F.EVENTDURATION, 0) / 1000 AS DURATION,
NULL AS CALLCOUNT,
@INTERNALRESOURCEGROUPID
FROM
#FILLINTERNALRESOURCESTABLE F

-- create internal execution resource for event sources
EXEC APM.InsertInternalResource

-- create performance node
INSERT INTO APM.PERFORMANCENODE
(
EVENTID,
RESOURCEID,
RESOURCEGROUPNODEID,
DESCRIPTION,
FUNCTIONNAME,
RESOURCEMETHOD,
DURATION,
ENTRYID,
SELFDURATION,
ISHEAVIESTNODE
)
SELECT
F.EVENTID,
R.RESOURCEID,
RGN.RESOURCEGROUPNODEID,
R.RESOURCEURI,
R.RESOURCEURI,
R.RESOURCEURI,
-- use event duration
F.EVENTDURATION / 1000,
0,
-- use event duration
F.EVENTDURATION / 1000,
--These events always have only one performance node which is most heavy
1
FROM
#FILLINTERNALRESOURCESTABLE F
JOIN APM.RESOURCEGROUPNODE RGN (NOLOCK) ON RGN.EVENTID = F.EVENTID
JOIN APM.RESOURCE R (NOLOCK) ON R.RESOURCEURI = N'Internal Execution' AND R.SOURCEID = F.SOURCEID

SET @RECORDS = @@ROWCOUNT

IF @TRACELEVEL = 4
BEGIN
-- trace message
DECLARE @PROCESSED INT
SELECT @PROCESSED = COUNT(*) FROM #FILLINTERNALRESOURCESTABLE
SELECT @MESSAGE = MESSAGE FROM APM.MESSAGES WHERE ID = 50028

RAISERROR (@MESSAGE, 0, 1, @PROCESSED, @RECORDS) WITH NOWAIT;
END

-- update event resource reference
EXEC APM.UpdateEventsByInternalResource N'performance'
END

/* Processing exception events which are not have exception nodes */
TRUNCATE TABLE #FILLINTERNALRESOURCESTABLE
INSERT INTO #FILLINTERNALRESOURCESTABLE(EVENTID,SOURCEID,EXCEPTIONCLASS,DESCRIPTION)
SELECT
E.EVENTID, E.SOURCEID, E.EXCEPTIONCLASS, E.DESCRIPTION
FROM
APM.EVENT (NOLOCK) E
WHERE
E.SEVIEWERDBID = @DATABASEID
AND E.EVENTID &gt;= @STARTID AND E.EVENTID &lt;= @ENDID
AND NOT EXISTS(SELECT * FROM EXCEPTIONNODE Ex (NOLOCK) WHERE Ex.EVENTID = E.EVENTID)
AND E.EVENTCLASSTYPE = N'exception' OPTION(RECOMPILE)
IF (@@ROWCOUNT &gt; 0)
BEGIN
-- create internal execution resource for event sources
EXEC APM.INSERTINTERNALRESOURCE

-- create exception node
INSERT INTO APM.EXCEPTIONNODE
(
EVENTID,
RESOURCEID,
EXCEPTIONCLASS,
FUNCTIONNAME,
RESOURCEMETHOD,
-- use event description
DESCRIPTION
)
SELECT
F.EVENTID,
R.RESOURCEID,
F.EXCEPTIONCLASS,
R.RESOURCEURI,
R.RESOURCEURI,
F.DESCRIPTION
FROM
#FILLINTERNALRESOURCESTABLE F
JOIN APM.RESOURCE R (NOLOCK) ON R.RESOURCEURI = N'Internal Execution' AND R.SOURCEID = F.SOURCEID

SELECT @RECORDS = @@ROWCOUNT

IF @TRACELEVEL = 4
BEGIN
-- trace message
SELECT @MESSAGE = MESSAGE FROM APM.MESSAGES WHERE ID = 50029
RAISERROR (@MESSAGE, 0, 1, @RECORDS) WITH NOWAIT;
END

-- update event resource reference
EXEC APM.UpdateEventsByInternalResource N'exception'
END


/* Processing performance nodes which are not have resources */
TRUNCATE TABLE #FILLINTERNALRESOURCESTABLE
INSERT INTO #FILLINTERNALRESOURCESTABLE(EVENTID,EVENTDURATION, SOURCEID)
SELECT
E.EVENTID, E.EVENTDURATION, E.SOURCEID
FROM
APM.EVENT (NOLOCK) E
WHERE
EXISTS(
SELECT * FROM APM.PERFORMANCENODE AS P(NOLOCK)
WHERE P.EVENTID = E.EVENTID AND P.RESOURCEID IS NULL
)
AND E.SEVIEWERDBID = @DATABASEID
AND E.EVENTID &gt;= @STARTID AND E.EVENTID &lt;= @ENDID
AND (E.HEAVYLIGHT IS NULL OR E.HEAVYLIGHT &lt;&gt; 0)
AND E.EVENTCLASSTYPE = N'performance' OPTION(RECOMPILE)

IF @@ROWCOUNT &gt; 0
BEGIN
--delete not linked resource nodes
DELETE RGN
FROM APM.RESOURCEGROUPNODE RGN
JOIN #FILLINTERNALRESOURCESTABLE F ON F.EVENTID = RGN.EVENTID
WHERE NOT EXISTS(SELECT * FROM APM.PERFORMANCENODE P (NOLOCK)
WHERE P.EVENTID = F.EVENTID AND P.RESOURCEGROUPNODEID = RGN.RESOURCEGROUPNODEID)
--Check existing internal group node
IF NOT EXISTS(
SELECT *
FROM APM.RESOURCEGROUPNODE AS RGN (NOLOCK)
JOIN #FILLINTERNALRESOURCESTABLE F ON F.EVENTID = RGN.EVENTID
WHERE
RGN.RESOURCEGROUPID = @INTERNALRESOURCEGROUPID
)
BEGIN
--Internal resource group is missing
--Create new
INSERT APM.RESOURCEGROUPNODE(EVENTID, DURATION, RESOURCEGROUPID)
SELECT
F.EVENTID,
-- use event duration
COALESCE(F.EVENTDURATION, 0) / 1000 - COALESCE(A.DURATION, 0) DURATION,
@INTERNALRESOURCEGROUPID
FROM
#FILLINTERNALRESOURCESTABLE F
CROSS APPLY
(
SELECT
SUM(DURATION) DURATION
FROM
APM.RESOURCEGROUPNODE AS RGN (NOLOCK) WHERE RGN.EVENTID = F.EVENTID
) A
END
ELSE
BEGIN
---not linked resource group node have been removed. Therefore, need recalculate internal group node
UPDATE RGN
-- use event duration
SET RGN.DURATION = COALESCE(F.EVENTDURATION, 0) / 1000 - COALESCE(A.DURATION, 0)
FROM
APM.RESOURCEGROUPNODE RGN
JOIN #FILLINTERNALRESOURCESTABLE F ON F.EVENTID = RGN.EVENTID AND RGN.RESOURCEGROUPID = @INTERNALRESOURCEGROUPID
CROSS APPLY
(
SELECT
SUM(DURATION) DURATION
FROM
APM.RESOURCEGROUPNODE AS RGN2 (NOLOCK)
WHERE
RGN2.EVENTID = F.EVENTID
AND RGN2.RESOURCEGROUPID &lt;&gt; @INTERNALRESOURCEGROUPID
) A
END

-- create internal execution resources for event sources
EXEC APM.INSERTINTERNALRESOURCE

-- update resource and resource group node references for performance nodes
UPDATE P SET
P.RESOURCEID = R.RESOURCEID,
P.RESOURCEGROUPNODEID = RGN.RESOURCEGROUPNODEID,
P.RESOURCEMETHOD = R.RESOURCEURI,
P.SELFDURATION = P.DURATION
FROM
APM.PERFORMANCENODE P
JOIN #FILLINTERNALRESOURCESTABLE F ON F.EVENTID = P.EVENTID
JOIN APM.RESOURCEGROUPNODE RGN (NOLOCK) ON RGN.EVENTID = F.EVENTID AND RGN.RESOURCEGROUPID = @INTERNALRESOURCEGROUPID
JOIN APM.RESOURCE R (NOLOCK) ON R.RESOURCEURI = N'Internal Execution' AND R.SOURCEID = F.SOURCEID
WHERE P.RESOURCEID IS NULL

-- update resource reference on performance events
EXEC APM.UpdateEventsByInternalResource N'performance'
END

/* Processing exception nodes which are not have resources */
TRUNCATE TABLE #FILLINTERNALRESOURCESTABLE
INSERT INTO #FILLINTERNALRESOURCESTABLE(EVENTID,SOURCEID)
SELECT
E.EVENTID, E.SOURCEID
FROM
APM.EVENT (NOLOCK) E
WHERE
E.SEVIEWERDBID = @DATABASEID
AND E.EVENTID &gt;= @STARTID AND E.EVENTID &lt;= @ENDID
AND EXISTS(SELECT * FROM EXCEPTIONNODE Ex (NOLOCK) WHERE Ex.EVENTID = E.EVENTID AND Ex.RESOURCEID IS NULL)
AND E.EVENTCLASSTYPE = N'exception' OPTION(RECOMPILE)
IF (@@ROWCOUNT &gt; 0)
BEGIN
-- create internal execution resources for event sources
EXEC APM.INSERTINTERNALRESOURCE

-- update exception resource references
UPDATE EX
SET EX.RESOURCEID = R.RESOURCEID
FROM
APM.EXCEPTIONNODE EX
JOIN #FILLINTERNALRESOURCESTABLE F ON F.EVENTID = EX.EVENTID
JOIN APM.RESOURCE R (NOLOCK) ON R.RESOURCEURI = N'Internal Execution' AND R.SOURCEID = F.SOURCEID
END

/* Processing performance events which are not have resources */
TRUNCATE TABLE #FILLINTERNALRESOURCESTABLE
INSERT INTO #FILLINTERNALRESOURCESTABLE(EVENTID,SOURCEID)
SELECT
E.EVENTID,E.SOURCEID
FROM
APM.EVENT (NOLOCK) E
WHERE
E.SEVIEWERDBID = @DATABASEID
AND E.EVENTID &gt;= @STARTID AND E.EVENTID &lt;= @ENDID
AND (E.HEAVYLIGHT IS NULL OR E.HEAVYLIGHT &lt;&gt; 0)
AND E.RESOURCEID IS NULL
AND E.EVENTCLASSTYPE = N'performance' OPTION(RECOMPILE)
IF (@@ROWCOUNT &gt; 0)
-- update resource reference on performance events
EXEC APM.UpdateEventsByInternalResource N'performance'

/* Processing exception events which are not have resources */
TRUNCATE TABLE #FILLINTERNALRESOURCESTABLE
INSERT INTO #FILLINTERNALRESOURCESTABLE(EVENTID,SOURCEID)
SELECT
E.EVENTID,E.SOURCEID
FROM
APM.EVENT (NOLOCK) E
WHERE
E.SEVIEWERDBID = @DATABASEID
AND E.EVENTID &gt;= @STARTID AND E.EVENTID &lt;= @ENDID
AND E.RESOURCEID IS NULL
AND E.EVENTCLASSTYPE = N'exception' OPTION(RECOMPILE)
IF (@@ROWCOUNT &gt; 0)
-- update resource reference on exception events
EXEC APM.UpdateEventsByInternalResource N'exception'
END TRY
BEGIN CATCH
-- exception processing

-- check active transactions
IF (@@TRANCOUNT &gt; 0)
ROLLBACK TRAN

-- get context variables
SELECT
@ERRORNUMBER = ERROR_NUMBER()
,@ERRORSEVERITY = ERROR_SEVERITY()
,@ERRORSTATE = ERROR_STATE()
,@ERRORLINE = ERROR_LINE()
,@ERRORPROCEDURE = ISNULL(ERROR_PROCEDURE(), '-')
,@ERRORMESSAGETEXT = ERROR_MESSAGE()

-- switch error flag
SET @ERRORIND = 1
END CATCH

--report error if any
IF (@ERRORIND = 1)
BEGIN
DECLARE @ADJUSTEDERRORSEVERITY int

SET @ADJUSTEDERRORSEVERITY = CASE
WHEN @ERRORSEVERITY &gt; 18 THEN 18
ELSE @ERRORSEVERITY
END
SELECT @ERROR_MESSAGE = message FROM APM.Messages WHERE id = 50004
RAISERROR (@ERROR_MESSAGE, @ADJUSTEDERRORSEVERITY, 1
,@ERRORNUMBER
,@ERRORSEVERITY
,@ERRORSTATE
,@ERRORPROCEDURE
,@ERRORLINE
,@ERRORMESSAGETEXT
)
END
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.GetResource'), 'IsScalarFunction') IS NULL)
BEGIN
EXECUTE('CREATE FUNCTION APM.GetResource ()
RETURNS int
AS begin return 1 end')
END
GO
ALTER FUNCTION APM.GetResource (@METHOD nvarchar(255))
RETURNS nvarchar(255)
AS
BEGIN
RETURN
LEFT(
@METHOD,
CASE WHEN CHARINDEX(N'$', @METHOD) = 0 THEN LEN(@METHOD) ELSE CHARINDEX(N'$', @METHOD) - 1 END
)
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.GetResourceType'), 'IsScalarFunction') IS NULL)
BEGIN
EXECUTE('CREATE FUNCTION APM.GetResourceType ()
RETURNS int
AS begin return 1 end')
END
GO
ALTER FUNCTION [APM].[GetResourceType] (@RESOURCETYPE nvarchar(255))
RETURNS nvarchar(255)
AS
BEGIN
RETURN
CASE
WHEN @RESOURCETYPE LIKE N'Web%' OR @RESOURCETYPE LIKE N'WCF%' THEN N'WebService'
WHEN @RESOURCETYPE LIKE N'SQL%'
OR @RESOURCETYPE LIKE N'OLEDB%'
OR @RESOURCETYPE LIKE N'IBM DB2%'
OR @RESOURCETYPE LIKE N'Sybase%'
OR @RESOURCETYPE LIKE N'Query%'
OR @RESOURCETYPE LIKE N'ODBC%'
OR @RESOURCETYPE LIKE N'Oracle%'
OR @RESOURCETYPE LIKE N'ADOMD%'
THEN N'Database'
ELSE N'Internal'
END
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.ComputerResourceUtilization'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.ComputerResourceUtilization AS RETURN 1')
END
GO
/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: ComputerResourceUtilization */
/* USED IN: Computer resource utilization report */
/* INPUT PARAMETERS: */
/* @DATESTART - Start date of the priod */
/* @DATEEND - End date of the period */
/* @MACHINEIDS - List of machine Id, separated by comma. Exp: '4,5,6' */
/* @SORTORDER - Specifies field to which sorting should be applayed */
/* 1. CPU value */
/* 2. Memory value */
/* 3. I/O value */
/* 4. Request count */
/* @TOPROWCOUNT - defines number of top rows, which will be returned */
/************************************************************************************/

ALTER PROCEDURE APM.ComputerResourceUtilization
@DATESTART DateTime,
@DATEEND DateTime,
@MACHINEIDS NVARCHAR(MAX),
@SORTORDER INT,
@TOPROWCOUNT INT
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON

/****************************************************************************************/
/* ASSISTING TEMP TABLES */
/****************************************************************************************/
-- Filter table, which contains machine Ids
CREATE TABLE #COMPUTERPCOUNTERANALYSIS_FILTERTABLE
(
VALUEID INT
)
-- Split @MACHINEIDS and fill table with values from it
INSERT
INTO #COMPUTERPCOUNTERANALYSIS_FILTERTABLE
SELECT
CAST(p.value AS int)
FROM
APM.GetMultiParameters(@MACHINEIDS, N'') p

--Filter PerfHourly table for further manipulations
CREATE TABLE #COMPUTERPCOUNTERANALYSIS_PERFHOURLY
(
MACHINEID INT,
PCTYPE NVARCHAR(100) collate database_default,
SUMVALUE FLOAT,
MAXVALUE FLOAT,
SAMPLECOUNT BIGINT
)

INSERT
INTO #COMPUTERPCOUNTERANALYSIS_PERFHOURLY
SELECT
ph.MachineId AS MachineId,
t.type AS PCType,
ph.SumValue AS SumValue,
ph.MaxValue AS MaxValue,
ph.SampleCount AS SampleCount
FROM
APM.PerfHourly AS ph (NOLOCK)
JOIN APM.PCType AS t (NOLOCK) ON ph.PCTypeId = t.PCTypeId
JOIN #COMPUTERPCOUNTERANALYSIS_FILTERTABLE f ON ph.MachineId = f.VALUEID
WHERE
ph.UTCDate &gt;= @DATESTART
AND ph.UTCDate &lt; @DATEEND
AND ph.SourceId IS NULL
AND ph.PCProcessId IS NULL
AND t.Type IN (
N'\Processor\% Processor Time',
N'\Process\Private Bytes',
N'\Process\IO Data Bytes/sec',
N'\Apps\Monitored Requests')


/****************************************************************************************/
/* MAIN QUERY */
/****************************************************************************************/
;WITH ComputerResourceUtilization AS
(
SELECT
ph.MACHINEID,
AVG(CASE ph.PCTYPE WHEN N'\Processor\% Processor Time' THEN ph.SUMVALUE/SAMPLECOUNT END) AS ProcessorValue,
MAX(CASE ph.PCTYPE WHEN N'\Processor\% Processor Time' THEN ph.MAXVALUE END) AS MaxProcessorValue,
AVG(CASE ph.PCTYPE WHEN N'\Process\Private Bytes' THEN ph.SUMVALUE/SAMPLECOUNT END) AS MemoryValue,
MAX(CASE ph.PCTYPE WHEN N'\Process\Private Bytes' THEN ph.MAXVALUE END) AS MaxMemoryValue,
AVG(CASE ph.PCTYPE WHEN N'\Process\IO Data Bytes/sec' THEN ph.SUMVALUE/SAMPLECOUNT END) AS IOValue,
MAX(CASE ph.PCTYPE WHEN N'\Process\IO Data Bytes/sec' THEN ph.MAXVALUE END) AS MaxIOValue,
SUM(CASE ph.PCTYPE WHEN N'\Apps\Monitored Requests' THEN ph.SUMVALUE END) AS RequestValue
FROM
#COMPUTERPCOUNTERANALYSIS_PERFHOURLY AS ph
GROUP BY
ph.MACHINEID
),
OrderedDataSet AS
(
SELECT
ROW_NUMBER() OVER(ORDER BY
CASE @SORTORDER
WHEN 1 THEN cr.ProcessorValue
WHEN 2 THEN cr.MemoryValue
WHEN 3 THEN cr.IOValue
WHEN 4 THEN cr.RequestValue
END DESC
) AS Id,
m.Machine,
m.MachineId,
COALESCE(m.CPUCount, 1) AS CPUCount,
cr.ProcessorValue AS ProcessorValue,
cr.MaxProcessorValue AS MaxProcessorValue,
cr.MemoryValue/(1024*1024) AS MemoryValue,
cr.MaxMemoryValue/(1024*1024) AS MaxMemoryValue,
cr.IOValue/1024 AS IOValue,
cr.MaxIOValue/1024 AS MaxIOValue,
cr.RequestValue AS RequestValue,
-- Flag to define if cpu count is not null,
-- in case of CPUDefineFlag = 0, show warning message about it in report
COALESCE(m.CPUCount, 0) AS CPUDefineFlag
FROM
ComputerResourceUtilization AS cr
JOIN APM.Machine AS m (NOLOCK) ON m.MachineId = cr.MachineId
)
SELECT
*
FROM
OrderedDataSet
WHERE
Id &lt;= @TOPROWCOUNT
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.fn_nums'), 'IsTableFunction') IS NULL)
BEGIN
EXECUTE('CREATE FUNCTION APM.fn_nums() RETURNS TABLE
AS
RETURN
select clmn=1')
END
GO

ALTER FUNCTION APM.fn_nums(@N AS INT) RETURNS TABLE
AS
RETURN
WITH
L0 AS(SELECT 1 AS c UNION ALL SELECT 1),
L1 AS(SELECT 1 AS c FROM L0 AS A, L0 AS B),
L2 AS(SELECT 1 AS c FROM L1 AS A, L1 AS B),
L3 AS(SELECT 1 AS c FROM L2 AS A, L2 AS B),
L4 AS(SELECT 1 AS c FROM L3 AS A, L3 AS B),
L5 AS(SELECT 1 AS c FROM L4 AS A, L4 AS B),
Nums AS(SELECT ROW_NUMBER() OVER(ORDER BY c) AS n FROM L5)
SELECT n FROM Nums WHERE n &lt;= @N;
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.RemoveProcessIdFromName'), 'IsScalarFunction') IS NULL)
BEGIN
EXECUTE('CREATE FUNCTION APM.RemoveProcessIdFromName ()
RETURNS int
AS begin return 1 end')
END
GO
/************************************************************************************/
/* Object: Function */
/* Name: RemoveProcessIdFromName */
/* Returns: process name till # symbol. Exp: w3wp#1 -&gt; w3wp, w3wp -&gt; w3wp */
/* or process name till _ symbol. Exp: w3wp_123 -&gt; w3wp */
/* Parameters: */
/* @PROCESSNAME - Process name, from which #N will be removed */
/************************************************************************************/

ALTER FUNCTION APM.RemoveProcessIdFromName (@PROCESSNAME nvarchar(255))
RETURNS NVARCHAR(255)
AS
BEGIN
DECLARE @result nvarchar(255), @pos int

/* try to find w3wp#X instance formatting */
SET @pos = CHARINDEX(N'#', REVERSE(@PROCESSNAME))
SET @result = CASE WHEN @pos &gt; 0
THEN LEFT(@PROCESSNAME, LEN(@PROCESSNAME) - @pos)
ELSE @result END

/* if w3wp#X instance formatting is not found we will try */
/* to find w3wp_XXXX formatting */
IF @pos = 0
BEGIN
SET @pos = PATINDEX( '%[0-9][_]%', REVERSE(@PROCESSNAME))
SET @result = CASE WHEN @pos &gt; 0
THEN LEFT(@PROCESSNAME, LEN(@PROCESSNAME) - (@pos + 1))
ELSE @PROCESSNAME END
END

RETURN @result
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.ComputerResourceUtilizationBySource'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.ComputerResourceUtilizationBySource AS RETURN 1')
END
GO
/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: ComputerResourceUtilizationBySource */
/* USED IN: Computer resource utilization sub report */
/* INPUT PARAMETERS: */
/* @DATESTART - Start date of the priod */
/* @DATEEND - End date of the period */
/* @SOURCEIDS - List of the source id, separated by comma. Exp: '1,2,3' */
/* @MACHINEID - Machine Id for which data should be selected */
/* @SORTORDER - Specifies field to which sorting should be applayed */
/* 1. CPU value */
/* 2. Memory value */
/* 3. I/O value */
/* 4. Request count */
/************************************************************************************/

ALTER PROCEDURE APM.ComputerResourceUtilizationBySource
@DATESTART DATETIME,
@DATEEND DATETIME,
@SOURCEIDS NVARCHAR(MAX),
@MACHINEID NVARCHAR(255),
@SORTORDER INT
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON

/************************************************************************************/
/* PREPARE ASSISTING TEMP TABLES */
/************************************************************************************/

--Filter table, which contains source ids, transfered to SP in @SOURCEIDS parameter
CREATE TABLE #SOURCEPCOUNTERANALYSIS_FILTERTABLE(
VALUEID INT
)

-- Split computer ids list separated by comma and fill table with it
INSERT
INTO #SOURCEPCOUNTERANALYSIS_FILTERTABLE
SELECT
CAST(p.value AS INT)
FROM
--Splits incoming string. Uses comma as substring delimiter
APM.GetMultiParameters(@SOURCEIDS, N'') AS p

--Filter PerfHourly table to decrease records count fot further calcultaions
CREATE TABLE #PERFHOURLYBYMACHINE(
UTCDate DATETIME,
SOURCEID INT,
PCPROCESSID INT,
SUMVALUE FLOAT,
SAMPLECOUNT BIGINT,
PACKAGECOUNTER BIGINT,
MAXVALUE FLOAT,
TYPE NVARCHAR(MAX) collate database_default
)
INSERT INTO #PERFHOURLYBYMACHINE
SELECT
ph.UTCDate,
ph.sourceId,
ph.pcprocessId,
ph.SumValue,
ph.SampleCount,
ph.PackageCounter,
ph.MaxValue,
t.Type
FROM
APM.PerfHourly AS ph (NOLOCK)
JOIN APM.PCType AS t (NOLOCK) ON t.pctypeid = ph.pctypeid
WHERE
ph.UTCDate &gt;= @DATESTART
AND ph.UTCDate &lt; @DATEEND
AND ph.MachineId = @MACHINEID
AND t.type IN
(
N'\Process\% Processor Time',
N'\Process\IO Data Bytes/sec',
N'\Process\Private Bytes',
N'\Apps\Monitored Requests',
-- 'Processor% Processor Time' counter is taken to calculate application activity,
-- relative to hours, when machine had been sending counter
N'\Processor\% Processor Time'
)

--Assisting table for application pool forming
CREATE TABLE #PROCESSNAMEFORSOURCE(
SOURCE NVARCHAR(255) collate database_default,
SOURCEID INT,
EXTRAINFO NVARCHAR(MAX) collate database_default,
PROCESS NVARCHAR(255) collate database_default
)

--Insert source name with correspondent process name and extrainfo
INSERT INTO #PROCESSNAMEFORSOURCE
SELECT DISTINCT
S.Source,
ph.SOURCEID,
COALESCE(p.Extrainfo, N'') AS EXTRAINFO,
--Select process name till # symbol (w3wp#1 -&gt; w3wp, w3wp -&gt; w3wp)
APM.RemoveProcessIdFromName(p.Process) AS Process
FROM
#PERFHOURLYBYMACHINE AS ph
JOIN APM.Source AS s (NOLOCK) ON ph.SOURCEID = s.sourceId
JOIN APM.PCProcess AS p (NOLOCK) ON p.pcprocessId = ph.PCPROCESSID

/********************************************************************************/
/* MAIN QUERY */
/********************************************************************************/
--Get sources name, ids list separated by comma per app pool
;WITH AppPoolInfo AS
(
SELECT
c.EXTRAINFO,
c.PROCESS,
-- source names
(SELECT A.source AS [data()]
FROM
(
SELECT DISTINCT
N'''' + c1.SOURCE + N'''' + N',' AS source
FROM
#PROCESSNAMEFORSOURCE as c1
WHERE
c1.EXTRAINFO = c.EXTRAINFO
AND c1.PROCESS = c.PROCESS
) AS A
FOR XML PATH ('')
) AS AppPoolSources,
-- source ids
(SELECT A.sourceid AS [data()]
FROM
(
SELECT DISTINCT
CAST(c1.SOURCEID AS NVARCHAR) + N',' AS sourceid
FROM
#PROCESSNAMEFORSOURCE AS c1
WHERE
c1.EXTRAINFO = c.EXTRAINFO
AND c1.PROCESS = c.PROCESS
) AS A
FOR XML PATH ('')
) AS SourceIds
FROM
#PROCESSNAMEFORSOURCE AS c
JOIN #SOURCEPCOUNTERANALYSIS_FILTERTABLE AS f ON f.VALUEID = c.SOURCEID
GROUP BY
c.EXTRAINFO,
c.PROCESS
),
-- Filter sources for which data should be selected;
-- as info should be selected not only for transfered sources, but also for sources
-- in the same app pool
SourceFilter AS
(
--One application can be in the several app pools, so use DISTINCT
SELECT DISTINCT
s2.SOURCEID
FROM
#PROCESSNAMEFORSOURCE AS s1
JOIN #PROCESSNAMEFORSOURCE AS s2 ON s1.EXTRAINFO = s2.EXTRAINFO AND s1.PROCESS = s2.PROCESS
JOIN #SOURCEPCOUNTERANALYSIS_FILTERTABLE AS f ON s1.SOURCEID = f.VALUEID
),
--Filter PerfHourly by source
PerfHourlyBySource AS
(
SELECT
ph.UTCDate,
ph.PCPROCESSID,
ph.SUMVALUE,
ph.SAMPLECOUNT,
ph.PACKAGECOUNTER,
ph.MAXVALUE,
--This field is used for 'Apps\Monitored Requests' (this counter depends on source only, not process)
ph.SOURCEID,
ph.TYPE
FROM
#PERFHOURLYBYMACHINE AS ph (NOLOCK)
JOIN SourceFilter AS s ON s.SOURCEID = ph.SOURCEID
),
--Calculate resource utilization by process in one hour
ProcessHourlyResourceUtilization AS
(
SELECT
ph.UTCDate,
ph.pcprocessId,
ph.Type,
-- Select MAX value as in case of app pool, some of the application
-- could work only part of the hour, and the value should be taken for the
-- application worked for the longest period
MAX(ph.SumValue) AS SumValue,
MAX(ph.MaxValue) AS MaxValue,
MAX(ph.SampleCount) AS SampleCount,
MAX(ph.PackageCounter) AS PackageCounter
FROM
PerfHourlyBySource AS ph
WHERE
--This condition allows to exclude Monitored Requests counter
PCProcessId IS NOT NULL
GROUP BY
ph.UTCDate,
ph.pcprocessId,
ph.Type
),
--Calculate resource utilization by application in one hour
--application means - web application = AppPool, otherwise = processname
ApplicationHourlyResourceUtilization AS
(
SELECT
ph.UTCDate,
ph.Type,
SUM(ph.SampleCount)*1.0/MAX(ph.PackageCounter) AS InstanceCount,
--Select process name till # symbol
APM.RemoveProcessIdFromName(p.Process) AS ProcessName,
COALESCE(p.ExtraInfo, N'') AS ProcessExtraInfo,
SUM(SumValue)/SUM(SampleCount) AS AvgValue,
MAX(ph.MaxValue) AS MaxValue
FROM
ProcessHourlyResourceUtilization AS ph
JOIN APM.PCProcess AS p (NOLOCK) ON ph.PCProcessId = p.PCProcessId
GROUP BY
ph.UTCDate,
ph.Type,
APM.RemoveProcessIdFromName(p.Process),
p.ExtraInfo
),
--Calculate average application resource utilization over all specified period
ApplicationResourceUtilization AS
(
SELECT
ph.ProcessName,
ph.ProcessExtraInfo,
-- Number of hours when app was active
COUNT(DISTINCT ph.UTCDate) AS ApplicationAvailabilityHours,
-- Instance count should be same for different resource types in one hour for one process
-- and averaging them won't make any difference but allow to avoid one aggregation step
AVG(ph.InstanceCount) AS InstanceCount,
MAX(ph.InstanceCount) AS MaxInstanceCount,
AVG(CASE WHEN InstanceCount &lt; 1 THEN InstanceCount ELSE 1 END) AS AppActivity,
AVG(CASE WHEN ph.type = N'\Process\% Processor Time' THEN ph.AvgValue END) AS CPUAvgValue,
AVG(CASE WHEN ph.type = N'\Process\IO Data Bytes/sec' THEN ph.AvgValue END) AS IOAvgValue,
AVG(CASE WHEN ph.type = N'\Process\Private Bytes' THEN ph.AvgValue END) AS MemoryAvgValue,
MAX(CASE WHEN ph.type = N'\Process\% Processor Time' THEN ph.MaxValue END) AS CPUMaxValue,
MAX(CASE WHEN ph.type = N'\Process\IO Data Bytes/sec' THEN ph.MaxValue END) AS IOMaxValue,
MAX(CASE WHEN ph.type = N'\Process\Private Bytes' THEN ph.MaxValue END) AS MemoryMaxValue
FROM
ApplicationHourlyResourceUtilization AS ph
GROUP BY
ph.ProcessName,
ph.ProcessExtraInfo
),
--Count Monitored Requests for Application
ApplicationRequestCount AS
(
SELECT
c.EXTRAINFO,
c.PROCESS,
SUM(ph.SUMVALUE) AS RequestCount
FROM
PerfHourlyBySource AS ph
-- If source was running in several app pools
-- #PROCESSNAMEFORSOURCE would contain several rows for one sourceid.
-- In this case request count will be counted for all app pools
JOIN #PROCESSNAMEFORSOURCE AS c ON ph.SOURCEID = c.SOURCEID
WHERE
ph.type = N'\Apps\Monitored Requests'
GROUP BY
c.EXTRAINFO,
c.PROCESS
),
-- Count hours when computer sent counters.
-- This value is used to calculate application activity between hours
ComputerAvailabilityHours AS
(
SELECT
COUNT(DISTINCT ph.UTCDate) AS HoursCount
FROM
#PERFHOURLYBYMACHINE AS ph
WHERE
ph.SOURCEID IS NULL
AND ph.PCPROCESSID IS NULL
AND ph.TYPE = N'\Processor\% Processor Time'
),
OrderedDataSet AS
(
SELECT
ROW_NUMBER() OVER (ORDER BY
CASE @SORTORDER
WHEN 1 THEN res.CPUAvgValue
WHEN 2 THEN res.MemoryAvgValue
WHEN 3 THEN res.IOAvgValue
WHEN 4 THEN req.RequestCount
END DESC) AS Id,
b.ExtraInfo AS AppPoolName,
--Remove comma from the end
CASE b.AppPoolSources WHEN '' THEN '' ELSE LEFT(b.AppPoolSources, LEN(b.AppPoolSources)-1) END AS AppPoolSources,
-- SourceIds string is used for drillthrought report for transfering sources to it
b.SourceIds,
req.RequestCount,
-- Correct instance count and application activity with hours, when application was active
res.InstanceCount * (res.ApplicationAvailabilityHours*1.0/ca.HoursCount) AS InstanceCount,
res.MaxInstanceCount,
res.AppActivity * (res.ApplicationAvailabilityHours*1.0/ca.HoursCount) AS AppActivity,
-- Calculate resource utilization
res.CPUAvgValue/COALESCE(m.cpucount, 1) AS CPUAvgValue,
res.IOAvgValue/1024 AS IOAvgValue,
res.MemoryAvgValue/(1024*1024) AS MemoryAvgValue,
res.CPUMaxValue/COALESCE(m.cpucount, 1) AS CPUMaxValue,
res.IOMaxValue/1024 AS IOMaxValue,
res.MemoryMaxValue/(1024*1024) AS MemoryMaxValue,
-- This field used for chart value in subreport bottom,
-- and it should include application activity both for hour and for specified period (application availability),
-- in order to be consistan with computer resources
(CASE @SORTORDER
WHEN 1 THEN res.CPUAvgValue/COALESCE(m.cpucount, 1) * res.AppActivity * (res.ApplicationAvailabilityHours*1.0/ca.HoursCount)
WHEN 2 THEN res.MemoryAvgValue/(1024*1024) * res.AppActivity * (res.ApplicationAvailabilityHours*1.0/ca.HoursCount)
WHEN 3 THEN res.IOAvgValue/1024 * res.AppActivity * (res.ApplicationAvailabilityHours*1.0/ca.HoursCount)
WHEN 4 THEN req.RequestCount
END) AS OrderedValue
FROM
AppPoolInfo AS b
JOIN ApplicationResourceUtilization AS res ON res.ProcessExtraInfo = b.ExtraInfo AND res.ProcessName = b.Process
LEFT OUTER JOIN ApplicationRequestCount AS req ON req.ExtraInfo = b.ExtraInfo AND req.Process = b.Process
JOIN APM.Machine AS m (NOLOCK) ON m.machineid = @MACHINEID
-- This query has only one record, and this value is common for all sources,
-- so use CROSS JOIN
CROSS JOIN ComputerAvailabilityHours AS ca
)
SELECT
Id,
CASE
WHEN LEN(AppPoolName) &gt; 0 THEN AppPoolName + N' - '+ AppPoolSources
ELSE CASE AppPoolSources WHEN '' THEN '' ELSE SUBSTRING(AppPoolSources, 2, LEN(AppPoolSources)-2) END
END AS AppPoolName,
SourceIds,
RequestCount,
InstanceCount,
MaxInstanceCount,
AppActivity,
CPUAvgValue,
CPUMaxValue,
MemoryAvgValue,
MemoryMaxValue,
IOAvgValue,
IOMaxValue,
OrderedValue
FROM
OrderedDataSet
ORDER BY
Id
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.GetQueryDateCount'), 'IsScalarFunction') IS NULL)
BEGIN
EXECUTE('CREATE FUNCTION APM.GetQueryDateCount ()
RETURNS int
AS begin return 1 end')
END
GO
ALTER FUNCTION APM.GetQueryDateCount(@PERIODTYPE INT, @CURRENTDATE DATETIME) RETURNS INT
AS
BEGIN
RETURN
CASE @PERIODTYPE
WHEN 1 THEN 1
WHEN 2 THEN 7
WHEN 3 THEN 31
END
END
GO


--------------------End Helper function for the management_application_summary_quality_analysis_report ------------------


--------------------Helper function for the management_reports_breakdown_report ------------------

IF (OBJECTPROPERTY(OBJECT_ID('APM.GetDatePart'), 'IsScalarFunction') IS NULL)
BEGIN
EXECUTE('CREATE FUNCTION APM.GetDatePart ()
RETURNS int
AS begin return 1 end')
END
GO
alter FUNCTION APM.GetDatePart(@DATEPART nvarchar(10), @DATE dateTime) RETURNS INT
AS
BEGIN
RETURN
CASE @DATEPART
WHEN 'Hour' THEN Datepart(hh, @DATE)
WHEN 'WeekDay' THEN Datepart(dw, @DATE)
WHEN 'MonthDay' THEN Datepart(d, @DATE)
END
END
GO

-------------------End Helper function for the management_reports_breakdown_report-------------------

--------------------Temporary table----------------------
IF (OBJECTPROPERTY(OBJECT_ID('APM.DATES'), 'IsTable') IS NOT NULL)
BEGIN
DROP TABLE APM.DATES
END
GO
CREATE TABLE APM.DATES(
WeekDays smallint NULL,
HourDates smallint NULL,
MonthDays smallint NULL,
DatesId int NULL
)
GO

;WITH DATES_BUILD(WEEKDAYS,HOURDATES,MONTHDAYS, DatesId) AS
(
SELECT
CASE WHEN N &lt;= 7 THEN N END WEEKDAYS,
CASE WHEN N &lt;= 24 THEN N-1 END HOURDATES,
N AS MONTHDAYS,
N AS DatesId
FROM APM.FN_NUMS(31)
)
INSERT INTO APM.DATES SELECT * FROM DATES_BUILD
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.ApplicationResourceUtilization'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.ApplicationResourceUtilization AS RETURN 1')
END
GO
/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: ApplicationResourceUtilization */
/* USED IN: Application ResourceUtilization report */
/* INPUT PARAMETERS: */
/* @DATESTART - Start date of the priod */
/* @DATEEND - End date of the period */
/* @SOURCEIDS - List of source Id, separated by comma. Exp: '1,2,3' */
/* @MACHINEIDS - List of machine Id, separated by comma. Exp: '4,5,6' */
/* @SORTORDER - Specifies field to which sorting should be applayed */
/* 1. CPU value */
/* 2. Memory value */
/* 3. I/O value */
/* 4. Request count */
/* @TOPROWCOUNT - defines number of top rows, which will be returned */
/************************************************************************************/
ALTER PROCEDURE APM.ApplicationResourceUtilization
@DATESTART DATETIME,
@DATEEND DATETIME,
@SOURCEIDS NVARCHAR(MAX),
@MACHINEIDS NVARCHAR(MAX),
@SORTORDER INT,
@TOPROWCOUNT INT
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON

/****************************************************************************************/
/* ASSISTING TEMP TABLES */
/****************************************************************************************/

-- Filter table, which contains machine ids and source ids
-- typeid defines filter type - 1 for source and 2 for machine
-- valueId filter value - source id and machine id
CREATE TABLE #SOURCEMACHINEFILTERTABLE(
TYPEID INT,
VALUEID INT
)

-- Fill table #SOURCEMACHINEFILTERTABLE
INSERT
INTO #SOURCEMACHINEFILTERTABLE
SELECT
p.typeId AS TYPEID,
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@SOURCEIDS, @MACHINEIDS) AS p

-- Filter PerfHourly table to decrease nummber of rows for further manipulations.
-- Filtering by sources could not be done as some of the filtered sources can be in app pools,
-- so they should present in calculations
CREATE TABLE #PERFHOURLYFILTERBYMACHINE
(
UTCDate DATETIME,
SOURCEID INT,
MACHINEID INT,
PCPROCESSID INT,
SUMVALUE FLOAT,
SAMPLECOUNT BIGINT,
PACKAGECOUNTER BIGINT,
MAXVALUE FLOAT,
TYPE NVARCHAR(MAX) collate database_default
)

--Fill table #PERFHOURLYFILTERBYMACHINE
INSERT
INTO #PERFHOURLYFILTERBYMACHINE
SELECT
ph.UTCDate,
ph.sourceId,
ph.MachineId,
ph.pcprocessId,
ph.SumValue,
ph.SampleCount,
ph.PackageCounter,
ph.MaxValue,
t.Type
FROM
APM.PerfHourly AS ph (NOLOCK)
JOIN APM.PCType AS t (NOLOCK) ON t.pctypeid = ph.pctypeid
--Join with #SOURCEMACHINEFILTERTABLE provides filtering perfHourly by machineid
JOIN #SOURCEMACHINEFILTERTABLE AS f ON (f.TYPEID = 2 AND f.VALUEID = ph.MachineId)
WHERE
ph.UTCDate &gt;= @DATESTART
AND ph.UTCDate &lt; @DATEEND
AND t.type IN
(
N'\Process\% Processor Time',
N'\Process\IO Data Bytes/sec',
N'\Process\Private Bytes',
N'\Apps\Monitored Requests',
-- 'Processor% Processor Time' counter is taken to calculate application activity,
-- relative to hours, when machine sent counter
N'\Processor\% Processor Time'
)

--Assisting table for application pool forming
CREATE TABLE #PROCESSNAMEFORSOURCE(
SOURCE NVARCHAR(255) collate database_default,
SOURCEID INT,
MACHINEID INT,
EXTRAINFO NVARCHAR(MAX) collate database_default,
PROCESS NVARCHAR(255) collate database_default
)

-- Insert source and machine with correspondent process name and extrainfo
-- Here machine is used, as same source with same process name can run in different machines
INSERT INTO #PROCESSNAMEFORSOURCE
SELECT DISTINCT
S.Source,
ph.SOURCEID,
ph.MACHINEID,
COALESCE(p.Extrainfo, N'') AS EXTRAINFO,
--Select process name till # symbol (w3wp#1 -&gt; w3wp, w3wp -&gt; w3wp)
APM.RemoveProcessIdFromName(p.Process) AS Process
FROM
#PERFHOURLYFILTERBYMACHINE AS ph
JOIN APM.Source AS s (NOLOCK) ON ph.SOURCEID = s.sourceId
JOIN APM.PCProcess AS p (NOLOCK) ON p.pcprocessId = ph.PCPROCESSID

/********************************************************************************/
/* MAIN QUERY */
/********************************************************************************/
--Get sources name, ids list separated by comma per app pool
;WITH AppPoolInfo AS
(
SELECT
c.EXTRAINFO,
c.PROCESS,
c.MACHINEID,
-- all source names which have the same process name as passed in @SOURCEIDS
(SELECT A.source AS [data()]
FROM
(
SELECT DISTINCT
N'''' + c1.SOURCE + N'''' + N',' AS source
FROM
#PROCESSNAMEFORSOURCE AS c1
WHERE
c1.EXTRAINFO = c.EXTRAINFO
AND c1.PROCESS = c.PROCESS
AND c1.MACHINEID = c.MACHINEID
) AS A
FOR XML PATH ('')
) AS AppPoolSources,
--Select SourceIds list for application pool, this string is need to avoid drillthrought to other reports
(SELECT A.source AS [data()]
FROM
(
SELECT DISTINCT
CAST(c1.SOURCEID AS NVARCHAR(5)) + N',' AS source
FROM
#PROCESSNAMEFORSOURCE AS c1
WHERE
c1.EXTRAINFO = c.EXTRAINFO
AND c1.PROCESS = c.PROCESS
AND c1.MACHINEID = c.MACHINEID
) AS A
FOR XML PATH ('')
) AS SourceIds

FROM
#PROCESSNAMEFORSOURCE AS c
JOIN #SOURCEMACHINEFILTERTABLE AS f ON (f.TYPEID = 1 AND f.VALUEID = c.SOURCEID)
GROUP BY
c.EXTRAINFO,
c.PROCESS,
c.MACHINEID
),
-- Filter sources for which data should be selected;
-- as info should be selected not only for transfered sources, but also for sources
-- in the same app pool
SourceFilter AS
(
--One application can be in the several app pools, so use DISTINCT
SELECT DISTINCT
s2.SOURCEID
FROM
#PROCESSNAMEFORSOURCE AS s1
JOIN #PROCESSNAMEFORSOURCE AS s2 ON s1.EXTRAINFO = s2.EXTRAINFO AND s1.PROCESS = s2.PROCESS
JOIN #SOURCEMACHINEFILTERTABLE AS f ON (f.TYPEID = 1 AND s1.SOURCEID = f.VALUEID)
),
--Filter PerfHourly by source
PerfHourlyBySource AS
(
SELECT
ph.UTCDate,
ph.PCPROCESSID,
ph.MACHINEID,
ph.SUMVALUE,
ph.SAMPLECOUNT,
ph.PACKAGECOUNTER,
ph.MAXVALUE,
ph.SOURCEID,
ph.TYPE
FROM
#PERFHOURLYFILTERBYMACHINE AS ph (NOLOCK)
JOIN SourceFilter AS s ON s.SOURCEID = ph.SOURCEID
),
--Calculate resource utilization by processes on machines in one hour
ProcessHourlyResourceUtilization AS
(
SELECT
ph.MachineId,
ph.UTCDate,
ph.pcprocessId,
ph.Type,
-- Select MAX value as in case of app pool, some of the application
-- could work not whole hour, and the value should be taken for the
-- application worked for the longest period
MAX(ph.SumValue) AS SumValue,
MAX(ph.MaxValue) AS MaxValue,
MAX(ph.SampleCount) AS SampleCount,
MAX(ph.PackageCounter) AS PackageCounter
FROM
PerfHourlyBySource AS ph
WHERE
--This condition allows to exclude Monitored Requests counter
PCProcessId IS NOT NULL
GROUP BY
ph.MachineId,
ph.UTCDate,
ph.pcprocessId,
ph.Type
),
-- Calculate resource utilization by application in one hour.
-- Here "application" means - for web application = AppPool, otherwise = processname
ApplicationHourlyResourceUtilization AS
(
SELECT
ph.MachineId,
ph.UTCDate,
ph.Type,
SUM(ph.SampleCount)*1.0/MAX(ph.PackageCounter) AS InstanceCount,
--Select process name till # symbol
APM.RemoveProcessIdFromName(p.Process) AS ProcessName,
COALESCE(p.ExtraInfo, N'') AS ProcessExtraInfo,
SUM(SumValue)/SUM(SampleCount) AS AvgValue,
MAX(ph.MaxValue) AS MaxValue
FROM
ProcessHourlyResourceUtilization AS ph
JOIN APM.PCProcess AS p (NOLOCK) ON ph.PCProcessId = p.PCProcessId
GROUP BY
ph.MachineId,
ph.UTCDate,
ph.Type,
APM.RemoveProcessIdFromName(p.Process),
p.ExtraInfo
),
--Calculate average application resource utilization over all specified period per machine
ApplicationResourceUtilizationByMachines AS
(
SELECT
ph.MachineId,
ph.ProcessName,
ph.ProcessExtraInfo,
-- Number of hours when application was active
COUNT(DISTINCT ph.UTCDate) AS ApplicationAvailabilityHours,
-- Instance count should be same for different resource types in one hour for one process
-- and averaging them won't make any difference but allow to avoid one aggregation step
AVG(ph.InstanceCount) AS InstanceCount,
MAX(ph.InstanceCount) AS MaxInstanceCount,
AVG(CASE WHEN InstanceCount &lt; 1 THEN InstanceCount ELSE 1 END) AS AppActivity,
AVG(CASE WHEN ph.type = N'\Process\% Processor Time' THEN ph.AvgValue END) AS CPUAvgValue,
AVG(CASE WHEN ph.type = N'\Process\IO Data Bytes/sec' THEN ph.AvgValue END) AS IOAvgValue,
AVG(CASE WHEN ph.type = N'\Process\Private Bytes' THEN ph.AvgValue END) AS MemoryAvgValue,
MAX(CASE WHEN ph.type = N'\Process\% Processor Time' THEN ph.MaxValue END) AS CPUMaxValue,
MAX(CASE WHEN ph.type = N'\Process\IO Data Bytes/sec' THEN ph.MaxValue END) AS IOMaxValue,
MAX(CASE WHEN ph.type = N'\Process\Private Bytes' THEN ph.MaxValue END) AS MemoryMaxValue
FROM
ApplicationHourlyResourceUtilization AS ph
GROUP BY
ph.MachineId,
ph.ProcessName,
ph.ProcessExtraInfo
),
-- Count hours when computer sent counters.
-- This value is used to calculate application activity between hours
ComputerAvailabilityHours AS
(
SELECT
COUNT(DISTINCT ph.UTCDate) AS HoursCount,
ph.MACHINEID
FROM
#PERFHOURLYFILTERBYMACHINE AS ph
WHERE
ph.SOURCEID IS NULL
AND ph.PCPROCESSID IS NULL
AND ph.TYPE = N'\Processor\% Processor Time'
GROUP BY
ph.MACHINEID
),
-- Count Monitored Requests for Application on each machine
-- as source can run on different machines with same process name and app pool, but different sources set,
-- it is important to group by machine to, to avoid calculation of requests from the other app pool
ApplicationRequestCountByMachine AS
(
SELECT
ph.MACHINEID,
c.EXTRAINFO,
c.PROCESS,
SUM(ph.SUMVALUE) AS RequestCount
FROM
PerfHourlyBySource AS ph
-- If source was running in several app pools
-- #PROCESSNAMEFORSOURCE would contain several rows for one sourceid.
-- In this case request count will be counted for all app pools
JOIN #PROCESSNAMEFORSOURCE AS c ON (ph.SOURCEID = c.SOURCEID AND ph.MACHINEID = c.MACHINEID)
WHERE
ph.TYPE = N'\Apps\Monitored Requests'
GROUP BY
ph.MACHINEID,
c.EXTRAINFO,
c.PROCESS
),
--Summary application resource utilization info by machines
ApplicationResourceUtilization AS
(
SELECT
-- Enumerate computers within application by specified orderBy value
ROW_NUMBER() OVER (PARTITION BY
-- Application pool sources added to grouping as on different machines app pool with the same names
-- can contain different sources set, and app pools assumed to be same only
-- if its name and sources set are the same
appPool.ExtraInfo,
appPool.Process,
appPool.AppPoolSources
ORDER BY
CASE @SORTORDER
WHEN 1 THEN ph.CPUAvgValue/COALESCE(m.CPUCount, 1)
WHEN 2 THEN ph.MemoryAvgValue
WHEN 3 THEN ph.IOAvgValue
WHEN 4 THEN r.RequestCount
END DESC) AS ComputerId,
m.machine,
m.MachineId,
COALESCE(m.CpuCount, 1) AS CPUCount,
appPool.ExtraInfo,
appPool.Process,
-- Remove comma form the end of source list
CASE appPool.AppPoolSources WHEN '' THEN '' ELSE LEFT(appPool.AppPoolSources, LEN(appPool.AppPoolSources)-1) END AS AppPoolSources,
-- Use application activity during all period for instance count calculation and application activity
InstanceCount*ph.ApplicationAvailabilityHours*1.0/mc.HoursCount AS InstanceCount,
AppActivity*ph.ApplicationAvailabilityHours*1.0/mc.HoursCount AS AppActivity,
MaxInstanceCount AS MaxInstanceCount,
-- CPU load should be normalized on core count for each machine
CPUAvgValue/COALESCE(m.CPUCount, 1) AS CPUAvgValue,
CPUMaxValue/COALESCE(m.CPUCount, 1) AS CPUMaxValue,
IOAvgValue AS IOAvgValue,
IOMaxValue AS IOMaxValue,
MemoryAvgValue AS MemoryAvgValue,
MemoryMaxValue AS MemoryMaxValue,
r.RequestCount AS RequestCount,
appPool.SourceIds,
-- Flag to define if cpu count is not null,
-- in case of CPUDefineFlag = 0, show warning message about it in report
COALESCE(m.CPUCount, 0) AS CPUDefineFlag,
-- Calculate average value for SortBy field for application over all its machines
-- This value will be used to enumerate application by specified OrderBy Value
AVG(CASE @SORTORDER
WHEN 1 THEN ph.CPUAvgValue/COALESCE(m.CPUCount, 1)
WHEN 2 THEN ph.MemoryAvgValue
WHEN 3 THEN ph.IOAvgValue
END)
OVER (PARTITION BY appPool.ExtraInfo,
appPool.Process,
AppPoolSources ) AS OrderByValue,
-- For order by requests sum of requests should be calculated
SUM(r.RequestCount) OVER(PARTITION BY appPool.ExtraInfo,
appPool.Process,
AppPoolSources) AS ApplicationRequestCount
FROM
ApplicationResourceUtilizationByMachines AS ph
JOIN AppPoolInfo AS appPool ON (appPool.ExtraInfo = ph.ProcessExtraInfo AND
appPool.Process = ph.ProcessName AND
appPool.MachineId = ph.MachineId)
LEFT OUTER JOIN ApplicationRequestCountByMachine AS r ON (ph.ProcessName = r.Process
AND ph.ProcessExtraInfo = r.ExtraInfo
AND ph.MachineId = r.MachineId)
JOIN ComputerAvailabilityHours AS mc ON mc.MachineId = ph.MachineId
JOIN APM.Machine AS m (NOLOCK) ON m.MachineId = ph.MachineId
),
-- Value of Id field is duplicated for each application.
OrderedDataSet AS
(
SELECT
-- DENSE_RANK function returns equal id for equal values in Over expression
-- This allow to enumerate Application within result set by specified order by value
DENSE_RANK() OVER(ORDER BY
(CASE
WHEN @SORTORDER = 4 THEN ApplicationRequestCount
ELSE OrderByValue
END) DESC,
ExtraInfo,
AppPoolSources ) AS Id,
OrderByValue,
ComputerId,
machine,
MachineId,
CPUCount,
CASE
WHEN LEN(ExtraInfo) &gt; 0 THEN ExtraInfo + N' - '+ AppPoolSources
-- remove quotes from the start and end of the source name
ELSE CASE AppPoolSources WHEN '' THEN '' ELSE SUBSTRING(AppPoolSources, 2, LEN(AppPoolSources)-2) END
END AS AppPoolName,
CASE
WHEN LEN(ExtraInfo) &gt; 0 THEN ExtraInfo
ELSE CASE AppPoolSources WHEN '' THEN '' ELSE SUBSTRING(AppPoolSources, 2, LEN(AppPoolSources)-2) END
END AS ApplicationName,
InstanceCount,
MaxInstanceCount,
AppActivity,
CPUAvgValue,
CPUMaxValue,
IOAvgValue/1024 AS IOAvgValue,
IOMaxValue/1024 AS IOMaxValue,
MemoryAvgValue/(1024*1024) AS MemoryAvgValue,
MemoryMaxValue/(1024*1024) AS MemoryMaxValue,
RequestCount,
SourceIds,
CPUDefineFlag
FROM
ApplicationResourceUtilization
)
SELECT
*
FROM
OrderedDataSet
WHERE
Id &lt;= @TOPROWCOUNT
ORDER BY
Id
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.GetTop10MostFrequentFailureReport'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.GetTop10MostFrequentFailureReport AS RETURN 1')
END
GO
ALTER PROCEDURE APM.GetTop10MostFrequentFailureReport
@SOURCE NVARCHAR(MAX),
@COMPUTERS NVARCHAR(MAX),
@ENDDATE DATETIME,
@PERIOD INT,
@THRESHOLD INT,
@PROBLEM NVARCHAR(10),
@TIMEZONE INT,
@PMSTATUS NVARCHAR(50)
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON;

SET @ENDDATE = DATEADD(minute, -@TIMEZONE, @ENDDATE)

DECLARE @STARTDATE DATETIME
SET @STARTDATE = DATEADD(d, -APM.GetQueryDateCount(@PERIOD, @ENDDATE), @ENDDATE)

CREATE TABLE #GETTOP10MOSTFREQUENTFAILURE_SOURCEMACHINEMULTIVALUE
(
TYPEID int, VALUE int
)

INSERT
INTO #GETTOP10MOSTFREQUENTFAILURE_SOURCEMACHINEMULTIVALUE
SELECT
p.typeid,
cast(p.value AS Int)
FROM APM.GetMultiParameters(@SOURCE, @COMPUTERS) p

-- Filter table, which contains PM Statuses of Events
CREATE TABLE #PMSTATUSFILTERTABLE(
VALUEID INT
)

-- Fill table #PMSTATUSFILTERTABLE
INSERT
INTO #PMSTATUSFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@PMSTATUS, N'') AS p

DECLARE @LASTPERIODSTARTDATE DateTime
SET @LASTPERIODSTARTDATE = DATEADD(d, -APM.GetQueryDateCount(@PERIOD, @STARTDATE), @STARTDATE)

DECLARE @CURRENTPERIODENDDATE DateTime
SET @CURRENTPERIODENDDATE = DATEADD(d, APM.GetQueryDateCount(@PERIOD, @STARTDATE), @STARTDATE)


;WITH ExceptionProblems AS
(
SELECT
e.description,
e.category,
COUNT(
CASE
WHEN e.utceventdate &gt;= @STARTDATE AND e.utceventdate &lt; @CURRENTPERIODENDDATE
THEN e.eventid
END
) as EventsCount,
COUNT(
CASE
WHEN e.utceventdate &gt;= @LASTPERIODSTARTDATE AND e.utceventdate &lt; @STARTDATE
THEN e.eventid
END
) AS LastEventsCount,
MAX(e.SeViewerDBId) AS SeViewerDBId
FROM
APM.Event (NOLOCK) AS e
JOIN #GETTOP10MOSTFREQUENTFAILURE_SOURCEMACHINEMULTIVALUE AS f1 ON (f1.TYPEID = 1 AND e.sourceid = f1.VALUE)
JOIN #GETTOP10MOSTFREQUENTFAILURE_SOURCEMACHINEMULTIVALUE AS f2 ON (f2.TYPEID = 2 AND e.machineid = f2.VALUE)
JOIN #PMSTATUSFILTERTABLE AS f3 ON (f3.VALUEID = e.PMStatus)
WHERE
e.EventClassType = N'Exception'
AND (e.category LIKE @PROBLEM)
AND e.utceventdate &gt;= @LASTPERIODSTARTDATE
AND e.utceventdate &lt; @CURRENTPERIODENDDATE


GROUP BY
e.description, e.category
),
OrderedExceptionProblems AS
(
SELECT
ROW_NUMBER() OVER (ORDER BY EventsCount DESC) AS Id,
[description],
EventsCount,
LastEventsCount,
category,
db.[Address] AS SeViewer
FROM
ExceptionProblems AS e
JOIN APM.SeViewerDB AS db (NOLOCK) ON e.SeViewerDBId = db.SeViewerDBId
WHERE
EventsCount &gt; 0
),
GroupedExceptionProblems AS
(
SELECT
Id,
[description],
EventsCount,
LastEventsCount,
category,
SeViewer,
SUM(CASE WHEN Id &gt; 10 THEN EventsCount ELSE 0 END) OVER () AS OtherSum,
SUM(CASE WHEN Id &gt; 10 THEN LastEventsCount ELSE 0 END) OVER () AS OtherLastSum,
SUM(EventsCount) OVER () AS SummaryCount
FROM
OrderedExceptionProblems
)
SELECT
TOP 10 *
FROM
GroupedExceptionProblems ORDER BY Id
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.GetTop10MostFrequentPerformanceReport'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.GetTop10MostFrequentPerformanceReport AS RETURN 1')
END
GO
ALTER PROCEDURE APM.GetTop10MostFrequentPerformanceReport
@SOURCE NVARCHAR(MAX),
@COMPUTERS NVARCHAR(MAX),
@ENDDATE DATETIME,
@PERIOD INT,
@THRESHOLD INT,
@PROBLEM NVARCHAR(10),
@TIMEZONE INT,
@PMSTATUS NVARCHAR(50)
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON;

SET @ENDDATE = DATEADD(minute, -@TIMEZONE, @ENDDATE)

DECLARE @STARTDATE DateTime
SET @STARTDATE = DATEADD(d, -APM.GetQueryDateCount(@PERIOD, @ENDDATE), @ENDDATE)

DECLARE @LASTPERIODSTARTDATE DateTime
SET @LASTPERIODSTARTDATE = DATEADD(d, -APM.GetQueryDateCount(@PERIOD, @STARTDATE), @STARTDATE)

DECLARE @CURRENTPERIODENDDATE DateTime
SET @CURRENTPERIODENDDATE = DATEADD(d, APM.GetQueryDateCount(@PERIOD, @STARTDATE), @STARTDATE)

CREATE TABLE #GETTOP10MOSTFREQUENTPERFORMANCE_SOURCEMACHINEMULTIVALUE
(
TYPEID int, VALUE int
)
INSERT
INTO #GETTOP10MOSTFREQUENTPERFORMANCE_SOURCEMACHINEMULTIVALUE
SELECT
p.typeid,
cast(p.value AS Int)
FROM APM.GetMultiParameters(@SOURCE, @COMPUTERS) p

-- Filter table, which contains PM Statuses of Events
CREATE TABLE #PMSTATUSFILTERTABLE(
VALUEID INT
)

-- Fill table #PMSTATUSFILTERTABLE
INSERT
INTO #PMSTATUSFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@PMSTATUS, N'') AS p

CREATE INDEX idx_parametertmp ON #GETTOP10MOSTFREQUENTPERFORMANCE_SOURCEMACHINEMULTIVALUE(TYPEID) INCLUDE(VALUE)

;WITH PerformanceProblems AS
(
SELECT
COUNT(CASE WHEN e.utceventdate &gt;= @STARTDATE THEN e.eventid END) as IssuesCount,
AVG(CASE WHEN e.utceventdate &gt;= @STARTDATE THEN e.eventduration / 1000000 END) AS AvgDuration,
MAX(CASE WHEN e.utceventdate &gt;= @STARTDATE THEN e.eventduration / 1000000 END) AS MaxDuration,
COUNT(CASE WHEN e.utceventdate &lt; @STARTDATE THEN e.eventid END) AS LastIssuesCount,
e.rootnodename,
(CASE
WHEN pn.description IS NOT NULL THEN RIGHT(pn.description, LEN(pn.description) - CHARINDEX(':', pn.description))
ELSE N''
END) AS PerfNodeDescription
FROM
APM.Event (NOLOCK) AS e
JOIN #PMSTATUSFILTERTABLE AS f ON (f.VALUEID = e.PMStatus)
OUTER APPLY (
SELECT TOP(1)
description
FROM
APM.PerformanceNode (NOLOCK)
WHERE
EVENTID = e.EventId AND e.resourceid = resourceid
ORDER BY
SelfDuration DESC
) AS pn
WHERE
e.EventClassType = N'Performance' AND e.eventduration / 1000000.0 &gt;= @THRESHOLD
AND e.sourceid IN (SELECT VALUE FROM #GETTOP10MOSTFREQUENTPERFORMANCE_SOURCEMACHINEMULTIVALUE AS f1 WHERE f1.TYPEID = 1)
AND e.machineid IN (SELECT VALUE FROM #GETTOP10MOSTFREQUENTPERFORMANCE_SOURCEMACHINEMULTIVALUE AS f2 WHERE f2.TYPEID = 2)
AND (e.category LIKE @PROBLEM OR e.category IS NULL)
AND e.utceventdate &gt;= @LASTPERIODSTARTDATE
AND e.utceventdate &lt; @CURRENTPERIODENDDATE
AND (e.HeavyLight &lt;&gt; 0 OR e.HeavyLight IS NULL)


GROUP BY
e.rootnodename, (CASE
WHEN pn.description IS NOT NULL THEN RIGHT(pn.description, LEN(pn.description) - CHARINDEX(':', pn.description))
ELSE N''
END)
),
OrderedPerformanceProblems AS
(
SELECT
ROW_NUMBER() OVER (ORDER BY IssuesCount DESC) AS Id,
rootnodename,
PerfNodeDescription,
rootnodename + (CASE
WHEN LEN(PerfNodeDescription) &gt; 0
THEN ' slow at ' + PerfNodeDescription
ELSE N'' END) AS description,
IssuesCount,
AvgDuration,
MaxDuration,
LastIssuesCount,
(SELECT SUM(IssuesCount) FROM PerformanceProblems) AS SummaryCount
FROM
PerformanceProblems
WHERE
IssuesCount &gt; 0
),
GroupedPerformanceproblems AS
(
SELECT
Id,
rootnodename,
PerfNodeDescription,
description,
IssuesCount,
AvgDuration,
MaxDuration,
LastIssuesCount,
SUM(CASE WHEN Id &gt; 10 THEN IssuesCount ELSE 0 END) OVER () AS OtherSum,
SUM(CASE WHEN Id &gt; 10 THEN LastIssuesCount ELSE 0 END) OVER () AS OtherLastSum,
SUM(IssuesCount) OVER () AS SummaryCount
FROM
OrderedPerformanceProblems
)
SELECT
TOP(10) *
FROM
GroupedPerformanceproblems
ORDER BY
Id
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.GetTOP10NewExceptionProblems'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.GetTOP10NewExceptionProblems AS RETURN 1')
END
GO
ALTER PROCEDURE APM.GetTOP10NewExceptionProblems
@SOURCE NVARCHAR(MAX),
@COMPUTERS NVARCHAR(MAX),
@ENDDATE DATETIME,
@PERIOD INT,
@THRESHOLD INT,
@PROBLEM NVARCHAR(10),
@TIMEZONE INT
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON;

SET @ENDDATE = DATEADD(minute, -@TIMEZONE, @ENDDATE)

DECLARE @STARTDATE DATETIME
SET @STARTDATE = DATEADD(d, -APM.GetQueryDateCount(@PERIOD, @ENDDATE), @ENDDATE)

CREATE TABLE #GETTOP10NEWEXCEPTION_SOURCEMACHINEMULTIVALUE
(
TYPEID int, VALUE int
)
INSERT
INTO #GETTOP10NEWEXCEPTION_SOURCEMACHINEMULTIVALUE
SELECT
p.typeid,
cast(p.value AS Int)
FROM APM.GetMultiParameters(@SOURCE, @COMPUTERS) p

DECLARE @LASTPERIODSTARTDATE DateTime
SET @LASTPERIODSTARTDATE = DATEADD(d, -APM.GetQueryDateCount(@PERIOD, @STARTDATE), @STARTDATE)

DECLARE @CURRENTPERIODENDDATE DateTime
SET @CURRENTPERIODENDDATE = DATEADD(d, APM.GetQueryDateCount(@PERIOD, @STARTDATE), @STARTDATE)


;WITH NewExceptionProblems AS
(
SELECT
e.description,
e.category,
COUNT(DISTINCT e.eventid) as EventsCount,
MAX(e.SeViewerDBId) AS SeViewerDBId
FROM
APM.Event (NOLOCK) AS e
JOIN #GETTOP10NEWEXCEPTION_SOURCEMACHINEMULTIVALUE AS f1 ON (f1.VALUE = e.sourceid and f1.TYPEID = 1)
JOIN #GETTOP10NEWEXCEPTION_SOURCEMACHINEMULTIVALUE AS f2 ON (f2.VALUE = e.machineid and f2.TYPEID = 2)
JOIN APM.eventgroup (NOLOCK) AS eg ON e.eventGroupId = eg.EventGroupId
WHERE
e.EventClassType = N'Exception'
AND (e.category LIKE @PROBLEM)
AND e.utceventdate &gt;= @STARTDATE
AND e.utceventdate &lt; @CURRENTPERIODENDDATE
AND eg.firsteventdate &gt;= @STARTDATE
AND (e.PMStatus = 0)
GROUP BY
e.description, e.category
),
OrderedExceptionProblems AS
(
SELECT
ROW_NUMBER() OVER (ORDER BY EventsCount DESC) AS Id,
description,
EventsCount,
category,
db.Address AS SeViewer
FROM
NewExceptionProblems e
JOIN APM.SeViewerDB AS db (NOLOCK) ON e.SeViewerDBId = db.SeViewerDBId
),
GroupedExceptionProblems AS
(
SELECT
*,
SUM(CASE WHEN Id &gt; 10 THEN EventsCount ELSE 0 END) OVER() AS OtherSum,
SUM(EventsCount) OVER() AS EventsSum
FROM
OrderedExceptionProblems
)
SELECT
TOP 10 *
FROM
GroupedExceptionProblems
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.GetTOP10NewPerformanceProblems'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.GetTOP10NewPerformanceProblems AS RETURN 1')
END
GO
ALTER PROCEDURE APM.GetTOP10NewPerformanceProblems
@SOURCE NVARCHAR(MAX),
@COMPUTERS NVARCHAR(MAX),
@ENDDATE DATETIME,
@PERIOD INT,
@THRESHOLD INT,
@PROBLEM NVARCHAR(10),
@TIMEZONE INT
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON;

SET @ENDDATE = DATEADD(minute, -@TIMEZONE, @ENDDATE)

DECLARE @STARTDATE DATETIME
SET @STARTDATE = DATEADD(d, -APM.GetQueryDateCount(@PERIOD, @ENDDATE), @ENDDATE)

CREATE TABLE #GETTOP10NEWPERFORMANCE_SOURCEMACHINEMULTIVALUE
(
TYPEID int, VALUE int
)
INSERT
INTO #GETTOP10NEWPERFORMANCE_SOURCEMACHINEMULTIVALUE
SELECT
p.typeid,
cast(p.value AS Int)
FROM APM.GetMultiParameters(@SOURCE, @COMPUTERS) p

DECLARE @LASTPERIODSTARTDATE DateTime
SET @LASTPERIODSTARTDATE = DATEADD(d, -APM.GetQueryDateCount(@PERIOD, @STARTDATE), @STARTDATE)

DECLARE @CURRENTPERIODENDDATE DateTime
SET @CURRENTPERIODENDDATE = DATEADD(d, APM.GetQueryDateCount(@PERIOD, @STARTDATE), @STARTDATE)


;WITH NewPerformanceProblems AS
(
SELECT
COUNT(e.eventid) as IssuesCount,
AVG(e.eventduration / 1000000) AS AvgDuration,
MAX(e.eventduration / 1000000) AS MaxDuration,
e.rootnodename,
(CASE
WHEN pn.description IS NOT NULL THEN RIGHT(pn.description, LEN(pn.description) - CHARINDEX(':', pn.description))
ELSE N''
END) AS PerfNodeDescription
FROM
APM.Event AS e
JOIN #GETTOP10NEWPERFORMANCE_SOURCEMACHINEMULTIVALUE AS f1 ON (f1.VALUE = e.sourceid and f1.TYPEID = 1)
JOIN #GETTOP10NEWPERFORMANCE_SOURCEMACHINEMULTIVALUE AS f2 ON (f2.VALUE = e.machineid and f2.TYPEID = 2)
JOIN APM.eventgroup (NOLOCK) AS eg ON E.EventGroupId = eg.EventGroupId
OUTER APPLY (
SELECT TOP(1)
description
FROM
APM.PerformanceNode (NOLOCK)
WHERE
EVENTID = e.EventId AND e.resourceid = resourceid
ORDER BY
SelfDuration DESC
) AS pn
WHERE
e.EventClassType = N'Performance' AND e.eventduration / 1000000.0 &gt;= @THRESHOLD
AND (e.category LIKE @PROBLEM OR e.category IS NULL)
AND e.utceventdate &gt;= @STARTDATE
AND e.utceventdate &lt; @CURRENTPERIODENDDATE
AND eg.firsteventdate &gt;= @STARTDATE
AND eg.firsteventdate &lt; @CURRENTPERIODENDDATE
AND (e.HeavyLight &lt;&gt; 0 OR e.HeavyLight IS NULL)
AND (e.PMStatus = 0)
GROUP BY
e.rootnodename, (CASE
WHEN pn.description IS NOT NULL THEN RIGHT(pn.description, LEN(pn.description) - CHARINDEX(':', pn.description))
ELSE N''
END)
),
OrderedPerformanceProblems AS
(
SELECT
ROW_NUMBER() OVER (ORDER BY IssuesCount DESC) AS Id,
rootnodename,
PerfNodeDescription,
rootnodename + (CASE
WHEN LEN(PerfNodeDescription) &gt; 0
THEN ' slow at ' + PerfNodeDescription
ELSE N'' END) AS description,
IssuesCount,
AvgDuration,
MaxDuration
FROM
NewPerformanceProblems
),
GroupedPerformanceProblems AS
(
SELECT
*,
SUM(CASE WHEN Id &gt; 10 THEN IssuesCount ELSE 0 END) OVER() AS OtherSum,
SUM(IssuesCount) OVER() AS SummaryCount
FROM
OrderedPerformanceProblems
)
SELECT
TOP 10 *
FROM
GroupedPerformanceProblems
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.GetAbsDateByRelative'), 'IsScalarFunction') IS NULL)
BEGIN
EXECUTE('CREATE FUNCTION APM.GetAbsDateByRelative ()
RETURNS int
AS begin return 1 end')
END
GO
ALTER FUNCTION APM.GetAbsDateByRelative(@RELATIVEDATE INT) RETURNS DATETIME
AS
BEGIN
RETURN
CASE @RELATIVEDATE
WHEN 10 THEN DATEADD(d, -(DATEPART(WEEKDAY, GETDATE()) - 1), GETDATE())
WHEN 20 THEN DATEADD(d, (7 - DATEPART(WEEKDAY, GETDATE())), GETDATE())
WHEN 30 THEN DATEADD(WEEK, -1, DATEADD(d, -(DATEPART(WEEKDAY, GETDATE()) - 1), GETDATE()))
WHEN 40 THEN DATEADD(WEEK, -1, DATEADD(d, (7 - DATEPART(WEEKDAY, GETDATE())), GETDATE()))
WHEN 50 THEN DATEADD(DAY, -(DATEPART(DAY, GETDATE()) - 1), GETDATE())
WHEN 60 THEN DATEADD(d, -DATEPART(DAY, DATEADD(MONTH, 1, GETDATE())), DATEADD(MONTH, 1, GETDATE()))
WHEN 70 THEN DATEADD(MONTH, -1, DATEADD(DAY, -(DATEPART(DAY, GETDATE()) - 1), GETDATE()))
WHEN 80 THEN DATEADD(DAY, -DATEPART(DAY, GETDATE()), GETDATE())
WHEN 90 THEN GETDATE()
WHEN 100 THEN DATEADD(DAY, -1, GETDATE())
WHEN 110 THEN DATEADD(DAY, 1, GETDATE())
END
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('apm.Split'), 'IsTableFunction') IS NOT NULL)
BEGIN
DROP FUNCTION apm.Split
END
GO

CREATE FUNCTION apm.Split(@String NVARCHAR(MAX), @Delimiter NCHAR(1) = N',')
RETURNS @temptable TABLE
(
items NVARCHAR(MAX)
)
AS
BEGIN
DECLARE @idx INT
DECLARE @slice NVARCHAR(MAX)

SELECT @idx = 1

IF @Delimiter IS NULL OR LEN(@Delimiter) &lt; 1
return;

IF @String IS NULL OR LEN(@String) &lt; 1
return;

WHILE @idx!= 0
BEGIN
SET @idx = CHARINDEX(@Delimiter,@String)
IF @idx!=0
SET @slice = LEFT(@String,@idx - 1)
ELSE
SET @slice = @String

IF(LEN(@slice)&gt;0)
INSERT INTO @temptable(Items) VALUES(@slice)

SET @String = RIGHT(@String,LEN(@String) - @idx)
IF LEN(@String) = 0 BREAK
END
RETURN
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.GetMultiParameters'), 'IsTableFunction') IS NOT NULL)
BEGIN
DROP FUNCTION APM.GetMultiParameters
END
GO

create FUNCTION APM.GetMultiParameters(@PARAMETER1 NVARCHAR(MAX), @PARAMETER2 NVARCHAR(MAX))
RETURNS @RESULT TABLE
(
ID INT,
TYPEID INT,
VALUE NVARCHAR(MAX)
)
AS
BEGIN
;WITH Filters AS
(
SELECT
1 AS typeId, items AS [Value]
FROM
apm.Split(@PARAMETER1, ',')
UNION ALL
SELECT
2 AS typeId, items AS [Value]
FROM
apm.Split(@PARAMETER2, ',')
)
INSERT INTO @RESULT
SELECT
ROW_NUMBER() OVER (ORDER BY typeId, [Value]) AS Id,
typeId,
RTRIM(LTRIM([value])) AS Value
FROM
Filters

RETURN
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.ResourceUtilizationTrend'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.ResourceUtilizationTrend AS RETURN 1')
END
GO
/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: ResourceUtilizationTrend */
/* USED IN: Day of Week Utilization, Hour of Day Utilization, */
/* Utilization Trend reports */
/* INPUT PARAMETERS: */
/* @SOURCEIDS - List of source Id, separated by comma. Exp: '1,2,3' */
/* @MACHINEIDS - List of machine Id, separated by comma. Exp: '4,5,6' */
/* @STARTDATE - Start date of the priod */
/* @ENDDATE - End date of the period */
/* @TIMEZONE - Time offset relative to UTC. Used in SP to calculate */
/* period in UTC and for conversion UTC time back */
/* to user time (for showing in trend chart) */
/* @GROUPBY - Specifies result gouping type. Possible values: */
/* Hour - Group by hours. Rersult set will contain 24 rows */
/* corresponding to 24 hours. Date field - 0-23, Hour field - 0 */
/* WeekDay - Group by week days. For this grouping type extra grouping */
/* is applied - by hours. So result data set contains 7*24 rows. */
/* Date field values - 1-7, Hour fields - 0-23 */
/* Date - Group by date. Number of row equal to days count in specified*/
/* period. If extra parameter @GROUPBYHOUR = 1, then extra grouping*/
/* by hours applied. If @GROUPBYHOUR = 0, than date field values - */
/* 0-(@ENDDATE-@STARTDATE) and Hour field - 0.If @GROUPBYHOUR = 1*/
/* than date field values - 0-(@ENDDATE-@STARTDATE) */
/* and Hour field - 0-23 */
/* @GROUPBYHOUR - flag to apply extra grouping by Hour. Available only for */
/* grouping by Date. */
/************************************************************************************/
ALTER PROCEDURE APM.ResourceUtilizationTrend
@SOURCEIDS NVARCHAR(MAX),
@MACHINEIDS NVARCHAR(MAX),
@STARTDATE DATETIME,
@ENDDATE DATETIME,
@TIMEZONE INT,
@GROUPBY NVARCHAR(10),
@PMSTATUS NVARCHAR(50),
@GROUPBYHOUR BIT = 0
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON;
/************************************************************************************************************************/
/* DECLARE SP VARIABLES */
/************************************************************************************************************************/
--Convert start date to utc format
DECLARE @UTCSTARTDATE DATETIME
SET @UTCSTARTDATE = DATEADD(minute, -@TIMEZONE, @STARTDATE)

--Convert end date to utc format
DECLARE @UTCENDDATE DATETIME
SET @UTCENDDATE = DATEADD(minute, -@TIMEZONE, @ENDDATE)

-- Day count in specified period
DECLARE @PERIOD INT
SET @PERIOD = ABS(DATEDIFF(day, @STARTDATE, @ENDDATE)) + 1

-- Define if extra grouping by hours should be applied
DECLARE @DOGROUPINGBYHOUR BIT
SET @DOGROUPINGBYHOUR = CASE
-- For group by WeekDay always do extra grouping by hours, for grouping by Date, only if @GROUPBYHOUR = 1 specified
WHEN @GROUPBY = 'WeekDay' THEN 1
WHEN (@GROUPBY = 'Date' AND @GROUPBYHOUR = 1) THEN 1
ELSE 0
END

DECLARE @PROCESSORCOUNTERID INT
SELECT @PROCESSORCOUNTERID = PCtypeId FROM APM.PCType (NOLOCK) WHERE type = N'\Process\% Processor Time'

DECLARE @MEMORYCOUNTERID INT
SELECT @MEMORYCOUNTERID = PCtypeId FROM APM.PCType (NOLOCK) WHERE type = N'\Process\Private Bytes'

DECLARE @IOCOUNTERID INT
SELECT @IOCOUNTERID = PCtypeId FROM APM.PCType (NOLOCK) WHERE type = N'\Process\IO Data Bytes/sec'

DECLARE @MONITOREDREQUESTCOUNTERID INT
SELECT @MONITOREDREQUESTCOUNTERID = PCtypeId FROM APM.PCType (NOLOCK) WHERE type = N'\Apps\Monitored Requests'

DECLARE @REQUESTTIMECOUNTERID INT
SELECT @REQUESTTIMECOUNTERID = PCtypeId FROM APM.PCType (NOLOCK) WHERE type = N'\Apps\Avg. Request Time'

/************************************************************************************************************/
/* PREPARE ASSISTING TABLES */
/************************************************************************************************************/
-- Filter table, which contains machine ids and source ids
-- typeid defines filter type - 1 for source and 2 for machine
-- valueId filter value - source id and machine id
CREATE TABLE #RESOURCEUTILIZATIONTREND_SOURCEMACHINEFILTERTABLE(
TYPEID INT,
VALUEID INT
)

-- Fill table #RESOURCEUTILIZATIONTREND_SOURCEMACHINEFILTERTABLE
INSERT
INTO #RESOURCEUTILIZATIONTREND_SOURCEMACHINEFILTERTABLE
SELECT
p.typeId AS TYPEID,
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@SOURCEIDS, @MACHINEIDS) AS p

-- Filter table, which contains PM Statuses of Events
CREATE TABLE #PMSTATUSFILTERTABLE(
VALUEID INT
)

-- Fill table #PMSTATUSFILTERTABLE
INSERT
INTO #PMSTATUSFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@PMSTATUS, N'') AS p

--Assisting table for application pool forming
CREATE TABLE #PROCESSNAMEFORSOURCE(
SOURCE NVARCHAR(255) collate database_default,
SOURCEID INT,
MACHINEID INT,
EXTRAINFO NVARCHAR(MAX) collate database_default,
PROCESS NVARCHAR(255) collate database_default
)

-- Insert source and machine with correspondent process name and extrainfo
-- Here machine is used, as same source with same process name can run in different machines
INSERT INTO #PROCESSNAMEFORSOURCE
SELECT DISTINCT
S.Source,
ph.SourceId,
ph.MachineId,
COALESCE(p.Extrainfo, N'') AS EXTRAINFO,
--Select process name till # symbol (w3wp#1 -&gt; w3wp, w3wp -&gt; w3wp)
APM.RemoveProcessIdFromName(p.Process) AS Process
FROM
(
SELECT DISTINCT
ph.SourceId,
ph.pcprocessId,
ph.MachineId
FROM
APM.PerfHourly AS ph (NOLOCK)
WHERE
ph.pcprocessId IS NOT NULL
AND ph.UTCDate &gt;= @UTCSTARTDATE
AND ph.UTCDate &lt; @UTCENDDATE
) AS ph
JOIN APM.PCProcess AS p (NOLOCK) ON p.pcprocessId = ph.pcprocessId
JOIN APM.Source AS s (NOLOCK) ON s.SourceId = ph.SourceId
JOIN #RESOURCEUTILIZATIONTREND_SOURCEMACHINEFILTERTABLE AS f ON (f.TYPEID = 2 AND ph.MachineId = f.VALUEID)



-- Assisting table, which contains filtered rows from Event table
CREATE TABLE #EVENTFILTER
(
EVENTID BIGINT,
SOURCEID INT,
SEVIEWERADDRESS NVARCHAR(MAX) collate database_default,
HOUR INT,
DATE INT
)

INSERT INTO #EVENTFILTER
SELECT
e.EventId,
E.SourceId,
-- Select event SeViewerd address to provide link to it in report
db.Address AS SEVIEWERADDRESS,
-- If grouping by hour should be done, then get hour from event date, else - 0
-- Hour will be in user time, not in UTC
(CASE
WHEN @DOGROUPINGBYHOUR = 1
THEN DATEPART(hour, DATEADD(mi, @TIMEZONE, e.utceventdate))
ELSE 0
END) AS HOUR,
-- Get grouping date (for week day - week day number1-7, for hour day hour 0-23,
-- for date - number of days between event date and specified period start day 0-(@ENDDATE-@STARTDATE))
-- This information is in user time
(CASE
WHEN @GROUPBY = 'Date'
THEN ABS(DATEDIFF(d, @STARTDATE, DATEADD(minute, @TIMEZONE, e.utceventdate)))
ELSE APM.GetDatePart(@GROUPBY, DATEADD(mi, @TIMEZONE, e.utceventdate))
END) AS DATE
FROM
APM.EVENT AS e
JOIN APM.SeViewerDB AS db ON e.seviewerdbid = db.seviewerdbid
JOIN #RESOURCEUTILIZATIONTREND_SOURCEMACHINEFILTERTABLE f1 ON e.SourceId = f1.VALUEID AND f1.TYPEID = 1
JOIN #RESOURCEUTILIZATIONTREND_SOURCEMACHINEFILTERTABLE f2 ON e.MachineId = f2.VALUEID AND f2.TYPEID = 2
JOIN #PMSTATUSFILTERTABLE AS f3 ON (f3.VALUEID = e.PMStatus)
WHERE
e.UTCEventDate &gt;= @UTCSTARTDATE
AND e.UTCEventDate &lt; @UTCENDDATE
AND (e.HeavyLight IS NULL OR e.HeavyLight &gt; 0)


/********************************************************************************/
/* MAIN QUERY */
/********************************************************************************/
-- Get sources name, ids list separated by comma per app pool
-- This info should be selected for all sources, even they are in the same application pool
-- as in this report grouping by source is applied not by application pool.
;WITH AppPoolInfo AS
(
SELECT
c.EXTRAINFO,
c.PROCESS,
c.SOURCEID,
-- all source names which have the same process name as passed in @SOURCEIDS
(SELECT A.source AS [data()]
FROM
(
SELECT DISTINCT
N'''' + c1.SOURCE + N'''' + N',' AS source
FROM
#PROCESSNAMEFORSOURCE AS c1
WHERE
c1.EXTRAINFO = c.EXTRAINFO
AND c1.PROCESS = c.PROCESS
AND c1.MACHINEID = c.MACHINEID
) AS A
FOR XML PATH ('')
) AS AppPoolSources
FROM
#PROCESSNAMEFORSOURCE AS c
JOIN #RESOURCEUTILIZATIONTREND_SOURCEMACHINEFILTERTABLE AS f ON (f.TYPEID = 1 AND f.VALUEID = c.SOURCEID)
GROUP BY
c.EXTRAINFO,
c.PROCESS,
c.MACHINEID,
c.SOURCEID
),
SourceDescription AS (
SELECT DISTINCT
CASE
-- For web application add app pool name before source list (remove comma from the source list end)
WHEN LEN(pd.ExtraInfo) &gt; 0 THEN pd.ExtraInfo + CASE pd.AppPoolSources WHEN '' THEN '' ELSE ' (' + LEFT(pd.AppPoolSources, LEN(pd.AppPoolSources) - 1) + ')' END
-- For executable application remove quotes from the start and end and remove comma
ELSE CASE pd.AppPoolSources WHEN '' THEN '' ELSE SUBSTRING(pd.AppPoolSources, 2, LEN(pd.AppPoolSources)-3) END

END AppPool,
pd.SourceId
FROM
AppPoolInfo AS pd
),
-- Forms application pool list for each source
-- Format: AppPool1 - ('Source1', 'Source2', Source3), AppPool2 - ('Source1', 'Source4')
SourceAppPools AS (
SELECT
s.SourceId,
-- Also select source name, to show it to user in report
s.Source,
(SELECT a.AppPool AS [data()]
FROM
(
SELECT DISTINCT
sd.AppPool + N', ' AS AppPool
FROM
SourceDescription as sd
WHERE
sd.SourceId = s.Sourceid
) AS A
FOR XML PATH ('')
) AS AggAppPool
FROM
#RESOURCEUTILIZATIONTREND_SOURCEMACHINEFILTERTABLE AS f
JOIN APM.Source AS s (NOLOCK) ON f.VALUEID = s.SourceId
WHERE
f.TYPEID = 1
),
-- Report frame. It contains all sources, for which data sould be selected,
-- and date values accordingly to specified period and grouping type.
SourcesDates AS
(
SELECT DISTINCT
-- Remove comma from the end
CASE sd.AggAppPool WHEN '' THEN '' ELSE LEFT(sd.AggAppPool, LEN(sd.AggAppPool) - 1) END AS AppPool,
sd.Source AS Source,
sd.SourceId AS SourceId,
-- Decrease hours to one. Result either 0-23, or 0 (if grouping by hours not specified)
Hours.n-1 AS hours,
D.date AS date
FROM
SourceAppPools AS sd
-- If groupng by hours should be applied, select values for hours 1-24, else select only one value - 1
CROSS JOIN APM.fn_nums(
(CASE
WHEN @DOGROUPINGBYHOUR = 1 THEN 24
ELSE 1
END)) AS Hours
-- Select date, depending on Group by parameter
CROSS JOIN (SELECT
(CASE
-- Values 0-23
WHEN @GROUPBY = 'Hour' THEN n-1
-- Values 1-7
WHEN @GROUPBY = 'WeekDay' THEN n
-- Values 0 - (@ENDDATE - @STARTDATE)
WHEN @GROUPBY = 'Date' THEN n - 1
END) AS date
FROM
APM.fn_nums(
CASE
WHEN @GROUPBY = 'Hour' THEN 24
WHEN @GROUPBY = 'WeekDay' THEN 7
WHEN @GROUPBY = 'Date' THEN (@PERIOD)
END
)
) AS D
),
-- Calculate resource utilization by SOURCE in one hour.
-- Here counter values are aggregated between sources assosiated with app pool (process).
-- If source presents in several app pools, then in this step values from all of them will be aggregated
SourceHourlyResourceUtilization AS
(
SELECT
ph.MachineId,
-- Single source is a source for which information should be selected
-- Information about each process assosiated with single source and consolidated for it
ph.SourceId AS SingleSourceId,
ph.UTCDate,
ph.PCTypeId,
SUM(ph.SampleCount)*1.0/MAX(ph.PackageCounter) AS InstanceCount,
SUM(SumValue)/SUM(SampleCount) AS AvgValue
FROM
APM.PerfHourly AS ph (NOLOCK)
--Join with #RESOURCEUTILIZATIONTREND_SOURCEMACHINEFILTERTABLE provides filtering perfHourly by sourceid
JOIN #RESOURCEUTILIZATIONTREND_SOURCEMACHINEFILTERTABLE AS f1 ON (f1.TYPEID = 1 AND f1.VALUEID = ph.SourceId)
--Join with #RESOURCEUTILIZATIONTREND_SOURCEMACHINEFILTERTABLE provides filtering perfHourly by machineid
JOIN #RESOURCEUTILIZATIONTREND_SOURCEMACHINEFILTERTABLE AS f2 ON (f2.TYPEID = 2 AND f2.VALUEID = ph.MachineId)
WHERE
ph.UTCDate &gt;= @UTCSTARTDATE
AND ph.UTCDate &lt; @UTCENDDATE
AND PCTypeId IN (@PROCESSORCOUNTERID, @MEMORYCOUNTERID, @IOCOUNTERID)
GROUP BY
ph.MachineId,
ph.SourceId,
ph.UTCDate,
ph.PCTypeId
),
--Calculate average source resource utilization for each resource type
ApplicationResourceUtilizationByType AS
(
SELECT
ph.MachineId,
ph.SingleSourceId,
-- If grouping by hour should be done, then get hour from PCounter date, else - 0
-- Hour will be in user time, not in UTC
(CASE
WHEN @DOGROUPINGBYHOUR = 1
THEN DATEPART(hour, DATEADD(mi, @TIMEZONE, ph.utcdate))
ELSE 0
END) AS Hour,
-- Get grouping date (for week day - week day number1-7, for hour day hour 0-23,
-- for date - number of days between PCounter date and specified period start day 0-(@ENDDATE-@STARTDATE))
-- This information is in user time
(CASE
WHEN @GROUPBY = 'Date'
THEN ABS(DATEDIFF(d, @STARTDATE, DATEADD(minute, @TIMEZONE, ph.utcdate)))
ELSE APM.GetDatePart(@GROUPBY, DATEADD(mi, @TIMEZONE, ph.utcdate))
END) AS Date,
-- Instance count should be same for different resource types in one hour for one process
-- and averaging them won't make any difference but allow to avoid one aggregation step
AVG(ph.InstanceCount) AS InstanceCount,
AVG(CASE WHEN ph.PCTypeId = @PROCESSORCOUNTERID THEN ph.AvgValue END) AS CPUAvgValue,
AVG(CASE WHEN ph.PCTypeId = @IOCOUNTERID THEN ph.AvgValue END) AS IOAvgValue,
AVG(CASE WHEN ph.PCTypeId = @MEMORYCOUNTERID THEN ph.AvgValue END) AS MemoryAvgValue
FROM
SourceHourlyResourceUtilization AS ph
GROUP BY
ph.MachineId,
ph.SingleSourceId,
ph.utcdate
),
--Calculate average source resource utilization for specified grouping date
ApplicationResourceUtilizationByGroupingDate AS
(
SELECT
ph.MachineId,
ph.SingleSourceId,
ph.Hour,
ph.Date,
AVG(InstanceCount) AS InstanceCount,
AVG(CPUAvgValue) AS CPUAvgValue,
AVG(IOAvgValue) AS IOAvgValue,
AVG(MemoryAvgValue) AS MemoryAvgValue
FROM
ApplicationResourceUtilizationByType AS ph
GROUP BY
ph.MachineId,
ph.SingleSourceId,
ph.Hour,
ph.Date
),
-- Calculate average source resource utilization between machines
-- This aggregation is actual then grouping type is longer than specified period.
-- Exp: Group by week day, period - month. Then grouping between all mondays in this month should be applied
ApplicationResourceUtilizationBetweenMachines AS
(
SELECT
ph.SingleSourceId,
ph.Hour,
ph.Date,
AVG(InstanceCount) AS InstanceCount,
AVG(CPUAvgValue/COALESCE(m.CPUCount, 1)) AS CPUAvgValue,
AVG(IOAvgValue) AS IOAvgValue,
AVG(MemoryAvgValue) AS MemoryAvgValue
FROM
ApplicationResourceUtilizationByGroupingDate AS ph
JOIN APM.Machine AS m (NOLOCK) ON m.MachineId = ph.MachineId
GROUP BY
ph.SingleSourceId,
ph.Hour,
ph.Date
),
-- Monitored requests and request average time calculation by mechines with specified grouping
-- For this counter type perfhourly table contain one record for source, utcdate and machine, so other grouping is redundant
RequestsBySources AS
(
SELECT
ph.SourceId,
ph.MachineId,
SUM(CASE WHEN ph.PCTypeId = @MONITOREDREQUESTCOUNTERID THEN ph.SumValue END) AS ReqCount,
AVG(CASE WHEN ph.PCTypeId = @REQUESTTIMECOUNTERID THEN ph.SumValue/ph.SampleCount END) AS AvgReqTime,
-- If grouping by hour should be done, then get hour from PCounter date, else - 0
-- Hour will be in user time, not in UTC
(CASE
WHEN @DOGROUPINGBYHOUR = 1
THEN DATEPART(hour, DATEADD(mi, @TIMEZONE, ph.utcdate))
ELSE 0
END) AS Hour,
-- Get grouping date (for week day - week day number1-7, for hour day hour 0-23,
-- for date - number of days between PCounter date and specified period start day 0-(@ENDDATE-@STARTDATE))
-- This information is in user time
(CASE
WHEN @GROUPBY = 'Date'
THEN ABS(DATEDIFF(d, @STARTDATE, DATEADD(minute, @TIMEZONE, ph.utcdate)))
ELSE APM.GetDatePart(@GROUPBY, DATEADD(mi, @TIMEZONE, ph.utcdate))
END) AS Date
FROM
APM.PerfHourly AS ph (NOLOCK)
--Join with #RESOURCEUTILIZATIONTREND_SOURCEMACHINEFILTERTABLE provides filtering perfHourly by sourceid
JOIN #RESOURCEUTILIZATIONTREND_SOURCEMACHINEFILTERTABLE AS f1 ON (f1.TYPEID = 1 AND f1.VALUEID = ph.SourceId)
--Join with #RESOURCEUTILIZATIONTREND_SOURCEMACHINEFILTERTABLE provides filtering perfHourly by machineid
JOIN #RESOURCEUTILIZATIONTREND_SOURCEMACHINEFILTERTABLE AS f2 ON (f2.TYPEID = 2 AND f2.VALUEID = ph.MachineId)
WHERE
ph.UTCDate &gt;= @UTCSTARTDATE
AND ph.UTCDate &lt; @UTCENDDATE
AND ph.PCTypeId IN (@MONITOREDREQUESTCOUNTERID, @REQUESTTIMECOUNTERID)
GROUP BY
ph.SourceId,
ph.MachineId,
-- This aggregation is actual then grouping type is longer than specified perid.
-- Exp: Group by week day, period - month. Then grouping between all mondays in this month should be applied
(CASE
WHEN @DOGROUPINGBYHOUR = 1
THEN DATEPART(hour, DATEADD(mi, @TIMEZONE, ph.utcdate))
ELSE 0
END),
(CASE
WHEN @GROUPBY = 'Date'
THEN ABS(DATEDIFF(d, @STARTDATE, DATEADD(minute, @TIMEZONE, ph.utcdate)))
ELSE APM.GetDatePart(@GROUPBY, DATEADD(mi, @TIMEZONE, ph.utcdate))
END)
),
--Calculate request between machines
RequestsBetweenMachines AS
(
SELECT
SourceId,
SUM(ReqCount) AS ReqCount,
AVG(AvgReqTime) AS AvgReqTime,
Hour,
Date
FROM
RequestsBySources
GROUP BY
SourceId,
Hour,
Date
),
Events AS
(
SELECT
COUNT(e.EVENTID) AS EventCount,
MAX(e.SEVIEWERADDRESS) AS SeViewerAddress,
e.SOURCEID,
e.HOUR,
e.DATE
FROM
#EVENTFILTER AS e
GROUP BY
e.SOURCEID,
e.HOUR,
e.DATE
),
-- Check that CPU count is defined for all computers, where application run.
-- Computers set, where application run, does not depend on specified period by design, as otherwise there is performance problems
MachineCPUUndefinedFlag AS
(
SELECT
sf.SOURCEID,
MIN(COALESCE(m.CPUCount, -1)) AS CPUUndefinedFlag
FROM
#PROCESSNAMEFORSOURCE AS sf
JOIN APM.Machine AS m (NOLOCK) ON sf.MACHINEID = m.MachineId
GROUP BY
sf.SOURCEID
)
SELECT
sd.Date,
sd.Hours,
sd.AppPool AS ApplicationPool,
sd.SourceId,
sd.Source AS SingleSource,
E.SeViewerAddress,
COALESCE(pc.InstanceCount, 0) AS NumberOfApplicationInstances,
COALESCE(req.ReqCount, 0) AS NumberOfRequests,
COALESCE(req.AvgReqTime, 0) AS AverageRequestTime,
COALESCE(pc.CPUAvgValue, 0) AS ResourceCPUUsage,
COALESCE(pc.IOAvgValue, 0) AS ResourceIO,
COALESCE(pc.MemoryAvgValue, 0) AS ResourceMemory,
COALESCE(e.EventCount, 0) AS NumberOfEvents,
-- cpuFlag.CPUUndefinedFlag is null for current source if there is no one PCounter row
-- in PerfHourly table for specified period. If so, there is no need to show message about it
COALESCE(cpuFlag.CPUUndefinedFlag, 1) AS CPUUndefinedFlag
FROM
SourcesDates AS sd
LEFT OUTER JOIN MachineCPUUndefinedFlag AS cpuFlag ON sd.Sourceid = cpuFlag.Sourceid
LEFT OUTER JOIN ApplicationResourceUtilizationBetweenMachines AS pc ON (sd.SourceId = pc.SingleSourceId AND pc.Hour = sd.Hours AND pc.Date = sd.Date)
LEFT OUTER JOIN RequestsBetweenMachines AS req ON (sd.SourceId = req.SourceId AND req.Hour = sd.Hours AND req.Date = sd.Date)
LEFT OUTER JOIN Events AS e ON (sd.SourceId = e.SourceId AND e.Hour = sd.Hours AND e.Date = sd.Date)
ORDER BY
sd.SourceId,
sd.Date,
sd.Hours
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.Source_sync'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.Source_sync AS RETURN 1')
END
GO
----------------------------------Sync procedures----------------------------------

/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: Source_sync */
/* USED IN: Synchronization source table. Call by Intercept Reporting Services */
/* INPUT PARAMETERS: */
/* @OBJECTKEYXML - xml package syncronization data */
/* @TRACELEVEL - trace level. Reserved. */
/* OUTPUT PARAMETERS: */
/* @ROWNOTAFFECTED - number of records from package which haven't been */
/* synchronized.Reserved. */
/* Note: */
/* If there are records which have not been transferred that they have been already */
/* transferred from other SEVIEWER database earlier. Any other reason will cause a */
/* exception at an insert */
/************************************************************************************/
ALTER PROCEDURE APM.Source_sync
@OBJECTKEYXML ntext,
@TRACELEVEL int,
@ROWNOTAFFECTED int output
AS
BEGIN
SET NOCOUNT ON

DECLARE
@ERRORIND bit
,@ERRORMESSAGE nvarchar(max)
,@ERRORNUMBER int
,@ERRORSEVERITY int
,@ERRORSTATE int
,@ERRORLINE int
,@ERRORPROCEDURE nvarchar(256)
,@ERRORMESSAGETEXT nvarchar(max)

SET @ERRORIND = 0

BEGIN TRY

SET @ROWNOTAFFECTED = 0

DECLARE
@EXECRESULT int
,@XMLDOCHANDLE int
,@ERROR_MESSAGE nvarchar(max)

EXEC @EXECRESULT = sp_xml_preparedocument @XMLDOCHANDLE OUTPUT, @OBJECTKEYXML
IF @EXECRESULT &lt;&gt; 0
BEGIN
SELECT @ERROR_MESSAGE = message FROM APM.messages WHERE id = 50002
RAISERROR(@ERROR_MESSAGE, 16, 1, 'Source_sync', @EXECRESULT)
END

DECLARE @SOURCE TABLE (
source nvarchar(255) NOT NULL
)

----Fill table from package
INSERT @SOURCE (
source
)
SELECT
source
FROM OPENXML(@XMLDOCHANDLE, 'rows/row', 2) WITH (
source nvarchar(255) ) xml

EXEC sp_xml_removedocument @XMLDOCHANDLE

SET @XMLDOCHANDLE = NULL

--insert not existing
INSERT APM.source (source)
SELECT DISTINCT sync.source
FROM @SOURCE sync
WHERE NOT EXISTS (SELECT * FROM APM.source WHERE (source = sync.source))

END TRY
BEGIN CATCH
IF (@@TRANCOUNT &gt; 0)
ROLLBACK TRAN

SELECT
@ERRORNUMBER = ERROR_NUMBER()
,@ERRORSEVERITY = ERROR_SEVERITY()
,@ERRORSTATE = ERROR_STATE()
,@ERRORLINE = ERROR_LINE()
,@ERRORPROCEDURE = ISNULL(ERROR_PROCEDURE(), '-')
,@ERRORMESSAGETEXT = ERROR_MESSAGE()

SET @ERRORIND = 1
END CATCH

IF @XMLDOCHANDLE IS NOT NULL
EXEC sp_xml_removedocument @XMLDOCHANDLE

-- report error if any
IF (@ERRORIND = 1)
BEGIN
DECLARE @ADJUSTEDERRORSEVERITY int

SET @ADJUSTEDERRORSEVERITY = CASE
WHEN @ERRORSEVERITY = 2601 OR @ERRORSEVERITY = 2627 THEN 0
WHEN @ERRORSEVERITY &gt; 18 THEN 18
ELSE @ERRORSEVERITY
END

SELECT @ERROR_MESSAGE = message FROM APM.Messages WHERE id = 50004
RAISERROR (@ERROR_MESSAGE, @ADJUSTEDERRORSEVERITY, 1
,@ERRORNUMBER
,@ERRORSEVERITY
,@ERRORSTATE
,@ERRORPROCEDURE
,@ERRORLINE
,@ERRORMESSAGETEXT
)
END
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.Machine_sync'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.Machine_sync AS RETURN 1')
END
GO
/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: Machine_sync */
/* USED IN: Synchronization machine table. Call by Intercept Reporting Services */
/* INPUT PARAMETERS: */
/* @OBJECTKEYXML - xml package syncronization data */
/* @TRACELEVEL - trace level. Reserved. */
/* OUTPUT PARAMETERS: */
/* @ROWNOTAFFECTED - number of records from package which haven't been */
/* synchronized.Reserved. */
/* Note: */
/* If there are records which have not been transferred that they have been already */
/* transferred from other SEVIEWER database earlier. Any other reason will cause a */
/* exception at an insert */
/************************************************************************************/
ALTER PROCEDURE APM.Machine_sync
@OBJECTKEYXML ntext
,@TRACELEVEL int
,@ROWNOTAFFECTED int output
AS
BEGIN
SET NOCOUNT ON

DECLARE
@ERRORIND bit
,@ERRORMESSAGE nvarchar(max)
,@ERRORNUMBER int
,@ERRORSEVERITY int
,@ERRORSTATE int
,@ERRORLINE int
,@ERRORPROCEDURE nvarchar(256)
,@ERRORMESSAGETEXT nvarchar(max)

SET @ERRORIND = 0

BEGIN TRY

SET @ROWNOTAFFECTED = 0

DECLARE
@EXECRESULT int
,@XMLDOCHANDLE int
,@ERROR_MESSAGE nvarchar(max)

EXEC @EXECRESULT = sp_xml_preparedocument @XMLDOCHANDLE OUTPUT, @OBJECTKEYXML
IF @EXECRESULT &lt;&gt; 0
BEGIN
SELECT @ERROR_MESSAGE = message FROM APM.messages WHERE id = 50002
RAISERROR(@ERROR_MESSAGE, 16, 1, 'machine_sync', @EXECRESULT)
END

DECLARE @MACHINE TABLE (
machinename nvarchar(255)
,windowsversion nvarchar(50)
,agentversion nvarchar(50)
,cpucount int
)

----Fill table from package
INSERT @MACHINE (
machinename
,windowsversion
,agentversion
,cpucount
)
SELECT
machinename
,windowsversion
,agentversion
,cpucount
FROM OPENXML(@XMLDOCHANDLE, 'rows/row', 2) WITH (
machinename nvarchar(255)
,windowsversion nvarchar(50)
,agentversion nvarchar(50)
,cpucount int ) xml

EXEC sp_xml_removedocument @XMLDOCHANDLE

SET @XMLDOCHANDLE = NULL

/*------------------ sync machine--------------------*/

---update existing
UPDATE m
SET machine = sync.machinename
,windowsversion = sync.windowsversion
,agentversion = COALESCE(sync.agentversion, m.agentversion)
,cpucount = COALESCE(sync.cpucount, m.cpucount)
FROM APM.machine m
JOIN @MACHINE sync ON sync.machinename = m.machine

DECLARE @ALLAPPID int
DECLARE @NEWMACHINES TABLE (machineId int)

--insert not existing
INSERT APM.machine (machine, windowsversion, agentversion, cpucount) OUTPUT INSERTED.MACHINEID INTO @NEWMACHINES
SELECT DISTINCT sync.machinename, sync.windowsversion, sync.agentversion, sync.cpucount
FROM @MACHINE sync
WHERE NOT EXISTS (SELECT * FROM APM.machine WHERE (machine = sync.machinename))

IF EXISTS(SELECT * FROM @NEWMACHINES)
BEGIN
IF @ALLAPPID IS NULL
SELECT @ALLAPPID = APPLICATIONID FROM APM.APPLICATION (NOLOCK) WHERE APPLICATION = N'All'
---- it is need to create the links with 'All' application group for new sources
INSERT APM.APPLICATIONSOURCEMACHINE
( APPLICATIONID ,
SOURCEID ,
MACHINEID
)
SELECT
@ALLAPPID
,s.SourceId
,m.machineId
FROM
APM.SOURCE (NOLOCK) AS s
CROSS JOIN @NEWMACHINES as m
WHERE
NOT EXISTS
(
SELECT * FROM APM.APPLICATIONSOURCEMACHINE (NOLOCK) AS a
WHERE a.SOURCEID = s.sourceId AND a.APPLICATIONID = @ALLAPPID AND m.machineId = a.machineid
)
END
END TRY
BEGIN CATCH
IF (@@TRANCOUNT &gt; 0)
ROLLBACK TRAN

SELECT
@ERRORNUMBER = ERROR_NUMBER()
,@ERRORSEVERITY = ERROR_SEVERITY()
,@ERRORSTATE = ERROR_STATE()
,@ERRORLINE = ERROR_LINE()
,@ERRORPROCEDURE = ISNULL(ERROR_PROCEDURE(), '-')
,@ERRORMESSAGETEXT = ERROR_MESSAGE()

SET @ERRORIND = 1
END CATCH

IF @XMLDOCHANDLE IS NOT NULL
EXEC sp_xml_removedocument @XMLDOCHANDLE

-- report error if any
IF (@ERRORIND = 1)
BEGIN
DECLARE @ADJUSTEDERRORSEVERITY int

SET @ADJUSTEDERRORSEVERITY = CASE
WHEN @ERRORSEVERITY = 2601 OR @ERRORSEVERITY = 2627 THEN 0
WHEN @ERRORSEVERITY &gt; 18 THEN 18
ELSE @ERRORSEVERITY
END

SELECT @ERROR_MESSAGE = message FROM APM.Messages WHERE id = 50004
RAISERROR (@ERROR_MESSAGE, @ADJUSTEDERRORSEVERITY, 1
,@ERRORNUMBER
,@ERRORSEVERITY
,@ERRORSTATE
,@ERRORPROCEDURE
,@ERRORLINE
,@ERRORMESSAGETEXT
)
END
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.PCType_sync'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.PCType_sync AS RETURN 1')
END
GO
/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: PCType_sync */
/* USED IN: Synchronization pctype table. Call by Intercept Reporting Services */
/* INPUT PARAMETERS: */
/* @OBJECTKEYXML - xml package syncronization data */
/* @TRACELEVEL - trace level. Reserved. */
/* OUTPUT PARAMETERS: */
/* @ROWNOTAFFECTED - number of records from package which haven't been */
/* synchronized.Reserved. */
/* Note: */
/* If there are records which have not been transferred that they have been already */
/* transferred from other SEVIEWER database earlier. Any other reason will cause a */
/* exception at an insert */
/************************************************************************************/
ALTER PROCEDURE APM.PCType_sync
@OBJECTKEYXML ntext,
@TRACELEVEL int,
@ROWNOTAFFECTED int output
AS
BEGIN
SET NOCOUNT ON

DECLARE
@ERRORIND bit
,@ERRORMESSAGE nvarchar(max)
,@ERRORNUMBER int
,@ERRORSEVERITY int
,@ERRORSTATE int
,@ERRORLINE int
,@ERRORPROCEDURE nvarchar(256)
,@ERRORMESSAGETEXT nvarchar(max)

SET @ERRORIND = 0

BEGIN TRY

SET @ROWNOTAFFECTED = 0

DECLARE
@EXECRESULT int
,@XMLDOCHANDLE int
,@ERROR_MESSAGE nvarchar(max)

EXEC @EXECRESULT = sp_xml_preparedocument @XMLDOCHANDLE OUTPUT, @OBJECTKEYXML
IF @EXECRESULT &lt;&gt; 0
BEGIN
SELECT @ERROR_MESSAGE = message FROM APM.messages WHERE id = 50002
RAISERROR(@ERROR_MESSAGE, 16, 1, 'PCType_sync', @EXECRESULT)
END

DECLARE @PCTYPE TABLE (
type nvarchar(255) collate database_default
,measure nvarchar(50) collate database_default
)

----Fill table from package
INSERT @PCTYPE (
type
,measure
)
SELECT
type
,measure
FROM OPENXML(@XMLDOCHANDLE, 'rows/row', 2) WITH (
type nvarchar(255)
,measure nvarchar(50) ) xml

EXEC sp_xml_removedocument @XMLDOCHANDLE

SET @XMLDOCHANDLE = NULL

--------------sync type---------
UPDATE T
SET Type = sync.type, measure = sync.measure
FROM APM.pctype T
JOIN @PCTYPE sync ON sync.type = T.Type

INSERT APM.pctype (type, measure)
SELECT DISTINCT sync.type, sync.measure
FROM @PCTYPE sync
WHERE NOT EXISTS (SELECT * FROM APM.PCType WHERE (type = sync.type))
END TRY
BEGIN CATCH
IF (@@TRANCOUNT &gt; 0)
ROLLBACK TRAN

SELECT
@ERRORNUMBER = ERROR_NUMBER()
,@ERRORSEVERITY = ERROR_SEVERITY()
,@ERRORSTATE = ERROR_STATE()
,@ERRORLINE = ERROR_LINE()
,@ERRORPROCEDURE = ISNULL(ERROR_PROCEDURE(), '-')
,@ERRORMESSAGETEXT = ERROR_MESSAGE()

SET @ERRORIND = 1
END CATCH

IF @XMLDOCHANDLE IS NOT NULL
EXEC sp_xml_removedocument @XMLDOCHANDLE

-- report error if any
IF (@ERRORIND = 1)
BEGIN
DECLARE @ADJUSTEDERRORSEVERITY int

SET @ADJUSTEDERRORSEVERITY = CASE
WHEN @ERRORSEVERITY = 2601 OR @ERRORSEVERITY = 2627 THEN 0
WHEN @ERRORSEVERITY &gt; 18 THEN 18
ELSE @ERRORSEVERITY
END

SELECT @ERROR_MESSAGE = message FROM APM.Messages WHERE id = 50004
RAISERROR (@ERROR_MESSAGE, @ADJUSTEDERRORSEVERITY, 1
,@ERRORNUMBER
,@ERRORSEVERITY
,@ERRORSTATE
,@ERRORPROCEDURE
,@ERRORLINE
,@ERRORMESSAGETEXT
)
END
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.Aspect_sync'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.Aspect_sync AS RETURN 1')
END
GO
/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: Aspect_sync */
/* USED IN: Synchronization aspect table. Call by Intercept Reporting Services */
/* INPUT PARAMETERS: */
/* @OBJECTKEYXML - xml package syncronization data */
/* @TRACELEVEL - trace level. Reserved. */
/* OUTPUT PARAMETERS: */
/* @ROWNOTAFFECTED - number of records from package which haven't been */
/* synchronized.Reserved. */
/* Note: */
/* If there are records which have not been transferred that they have been already */
/* transferred from other SEVIEWER database earlier. Any other reason will cause a */
/* exception at an insert */
/************************************************************************************/
ALTER PROCEDURE APM.Aspect_sync
@OBJECTKEYXML ntext
,@TRACELEVEL int
,@ROWNOTAFFECTED int output
AS
BEGIN
SET NOCOUNT ON

DECLARE
@ERRORIND bit
,@ERRORMESSAGE nvarchar(max)
,@ERRORNUMBER int
,@ERRORSEVERITY int
,@ERRORSTATE int
,@ERRORLINE int
,@ERRORPROCEDURE nvarchar(256)
,@ERRORMESSAGETEXT nvarchar(max)

SET @ERRORIND = 0

BEGIN TRY

DECLARE
@EXECRESULT int
,@XMLDOCHANDLE int
,@ERROR_MESSAGE nvarchar(max)

SET @ROWNOTAFFECTED = 0

EXEC @EXECRESULT = sp_xml_preparedocument @XMLDOCHANDLE OUTPUT, @OBJECTKEYXML
IF @EXECRESULT &lt;&gt; 0
BEGIN
SELECT @ERROR_MESSAGE = message FROM APM.messages WHERE id = 50002
RAISERROR(@ERROR_MESSAGE, 16, 1, 'Aspect_sync', @EXECRESULT)
END

DECLARE @ASPECT TABLE (
Aspect nvarchar(50) collate database_default NOT NULL
,Description nvarchar(255) collate database_default NULL
)

----Fill table from package
INSERT @ASPECT (
Aspect
,Description
)
SELECT
Aspect
,Description
FROM OPENXML(@XMLDOCHANDLE, 'rows/row', 2) WITH (
aspect nvarchar(50)
,description nvarchar(256) ) xml

EXEC sp_xml_removedocument @XMLDOCHANDLE

SET @XMLDOCHANDLE = NULL

---update existing
UPDATE asp
SET Aspect = sync.Aspect, Description = sync.Description
FROM APM.Aspect asp
JOIN @ASPECT sync ON sync.Aspect = asp.aspect

--insert not existing
INSERT APM.aspect (aspect, description)
SELECT DISTINCT sync.Aspect, sync.Description
FROM @ASPECT sync
WHERE NOT EXISTS (SELECT * FROM APM.Aspect WHERE (aspect = sync.Aspect))
END TRY
BEGIN CATCH
IF (@@TRANCOUNT &gt; 0)
ROLLBACK TRAN

SELECT
@ERRORNUMBER = ERROR_NUMBER()
,@ERRORSEVERITY = ERROR_SEVERITY()
,@ERRORSTATE = ERROR_STATE()
,@ERRORLINE = ERROR_LINE()
,@ERRORPROCEDURE = ISNULL(ERROR_PROCEDURE(), '-')
,@ERRORMESSAGETEXT = ERROR_MESSAGE()
SET @ERRORIND = 1
END CATCH

IF @XMLDOCHANDLE IS NOT NULL
EXEC sp_xml_removedocument @XMLDOCHANDLE

-- report error if any
IF (@ERRORIND = 1)
BEGIN
DECLARE @ADJUSTEDERRORSEVERITY int

SET @ADJUSTEDERRORSEVERITY = CASE
WHEN @ERRORSEVERITY = 2601 OR @ERRORSEVERITY = 2627 THEN 0
WHEN @ERRORSEVERITY &gt; 18 THEN 18
ELSE @ERRORSEVERITY
END
SELECT @ERROR_MESSAGE = message FROM APM.Messages WHERE id = 50004

RAISERROR (@ERROR_MESSAGE, @ADJUSTEDERRORSEVERITY, 1
,@ERRORNUMBER
,@ERRORSEVERITY
,@ERRORSTATE
,@ERRORPROCEDURE
,@ERRORLINE
,@ERRORMESSAGETEXT
)
END
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.EventGroup_sync'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.EventGroup_sync AS RETURN 1')
END
GO
/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: EventGroup_sync */
/* USED IN: Synchronization eventgroup and cseventgroup tables. */
/* Call by Intercept Reporting Services */
/* INPUT PARAMETERS: */
/* @OBJECTKEYXML - xml package syncronization data */
/* @TRACELEVEL - trace level. Reserved. */
/* OUTPUT PARAMETERS: */
/* @ROWNOTAFFECTED - number of records from package which haven't been */
/* synchronized. */
/************************************************************************************/
ALTER PROCEDURE [APM].[EventGroup_sync]
@OBJECTKEYXML ntext
,@TRACELEVEL int
,@ROWNOTAFFECTED int output
AS
BEGIN
SET NOCOUNT ON

DECLARE
@ERRORIND bit
,@ERRORMESSAGE nvarchar(max)
,@ERRORNUMBER int
,@ERRORSEVERITY int
,@ERRORSTATE int
,@ERRORLINE int
,@ERRORPROCEDURE nvarchar(256)
,@ERRORMESSAGETEXT nvarchar(max)

SET @ERRORIND = 0

BEGIN TRY

DECLARE
@EXECRESULT int
,@XMLDOCHANDLE int
,@ERROR_MESSAGE nvarchar(max)
,@UPDATED_ROWCOUNT int
,@INSERTED_ROWCOUNT int
,@CHANGED_ROWCOUNT int
,@MESSAGE nvarchar(max)

SET @ROWNOTAFFECTED = 0

EXEC @EXECRESULT = sp_xml_preparedocument @XMLDOCHANDLE OUTPUT, @OBJECTKEYXML
IF @EXECRESULT &lt;&gt; 0
BEGIN
SELECT @ERROR_MESSAGE = message FROM APM.messages WHERE id = 50002
RAISERROR(@ERROR_MESSAGE, 16, 1, 'EventGroup_sync', @EXECRESULT)
END

DECLARE @EVENTGROUP TABLE (
id int identity(1,1)
,source nvarchar(255) collate database_default
,firsteventdate datetime
,lasteventdate datetime
,eventclasstype nvarchar(50) collate database_default
,rootnodename nvarchar(255) collate database_default
,aspect nvarchar(50) collate database_default
,hashvalue nvarchar(50) collate database_default
,client bit
,description nvarchar(max) collate database_default
,sourceid int
)

--Fill temporary table from package
INSERT @EVENTGROUP (
source
,firsteventdate
,lasteventdate
,eventclasstype
,rootnodename
,aspect
,hashvalue
,client
,description
)
SELECT DISTINCT
source
,firsteventdate
,lasteventdate
,eventclasstype
,rootnodename
,aspect
,hashvalue
,CASE WHEN source LIKE '%(Client)' THEN 1 ELSE 0 END
,description
FROM OPENXML(@XMLDOCHANDLE, 'rows/row', 2) WITH (
source nvarchar(255)
,firsteventdate datetime
,lasteventdate datetime
,eventclasstype nvarchar(50)
,rootnodename nvarchar(255)
,aspect nvarchar(50)
,hashvalue nvarchar(50)
,description nvarchar(max)
) xml

EXEC sp_xml_removedocument @XMLDOCHANDLE

SET @XMLDOCHANDLE = NULL

--remove duplicates by hashvalue
Delete g1
from @EVENTGROUP g1
join @EVENTGROUP g2 on g1.id &gt; g2.id and g1.hashvalue = g2.hashvalue



----- sources can be removed using "Remove applications wizard" so it is need synchronize sources ----
DECLARE @NEWSOURCES TABLE (sourceid int)

INSERT APM.SOURCE (SOURCE) OUTPUT INSERTED.SOURCEID INTO @NEWSOURCES
SELECT DISTINCT source FROM @EVENTGROUP eg
WHERE NOT EXISTS (SELECT * FROM APM.source s (NOLOCK) WHERE s.source = eg.source)
IF EXISTS(SELECT * FROM @NEWSOURCES)
BEGIN
DECLARE @ALLAPPID int
SELECT @ALLAPPID = APPLICATIONID FROM APM.APPLICATION (NOLOCK) WHERE APPLICATION = N'All'
---- it is need to create the links with 'All' application group for new sources
INSERT APM.APPLICATIONSOURCEMACHINE
( APPLICATIONID ,
SOURCEID ,
MACHINEID
)
SELECT
@ALLAPPID
,s.sourceid
,m.machineId
FROM
APM.MACHINE (NOLOCK) AS m
CROSS JOIN @NEWSOURCES as s
WHERE
NOT EXISTS
(
SELECT * FROM APM.APPLICATIONSOURCEMACHINE (NOLOCK) AS a
WHERE a.SOURCEID = s.sourceid AND a.APPLICATIONID = @ALLAPPID AND m.MACHINEid = a.machineid
)
END

/*------------------sync eventgroup------------------*/

/* updating server or client event group */
IF EXISTS(SELECT * FROM @EVENTGROUP WHERE client = 0)
BEGIN
/* updating server event group records by hashavalue*/
UPDATE G
SET eventclasstype = sync.eventclasstype
,rootnodename = sync.rootnodename
,aspect = sync.aspect
,firsteventdate = CASE WHEN sync.firsteventdate &lt; g.firsteventdate THEN sync.firsteventdate ELSE g.firsteventdate END
,lasteventdate = CASE WHEN sync.lasteventdate &gt; g.lasteventdate THEN sync.lasteventdate ELSE g.lasteventdate END
,description = sync.description
,sourceid = s.SourceId
FROM APM.eventGroup g
JOIN @EVENTGROUP sync ON sync.hashvalue = g.hashvalue AND sync.client = 0
JOIN APM.Source AS s ON s.source = sync.source
/*Permit number of affected records*/
SET @UPDATED_ROWCOUNT = @@ROWCOUNT

/* Insert new server event group which are not found by hashvalue */
INSERT APM.eventgroup (
firsteventdate
,lasteventdate
,eventclasstype
,rootnodename
,aspect
,hashvalue
,description
,sourceid
)
SELECT DISTINCT
sync.firsteventdate
,sync.lasteventdate
,sync.eventclasstype
,sync.rootnodename
,sync.aspect
,sync.hashvalue
,sync.description
,s.SourceId
FROM @EVENTGROUP sync
JOIN APM.Source AS s ON s.source = sync.source
WHERE
sync.client = 0 AND NOT EXISTS (SELECT * FROM APM.eventgroup WHERE (hashvalue = sync.hashvalue))
SET @INSERTED_ROWCOUNT = @@ROWCOUNT

/* Log about inserted records for verbal log mode*/
IF @TRACELEVEL = 4
BEGIN
SELECT @MESSAGE = MESSAGE FROM APM.MESSAGES WHERE ID = 50024
RAISERROR (@MESSAGE, 0, 1, @INSERTED_ROWCOUNT, 'eventGroup') WITH NOWAIT;
END

/* Number of records from package */
SELECT @CHANGED_ROWCOUNT = COUNT(*) FROM @EVENTGROUP WHERE client = 0

/* Calculate not affected packages records which are not processing */
SET @ROWNOTAFFECTED = @CHANGED_ROWCOUNT - (@INSERTED_ROWCOUNT + @UPDATED_ROWCOUNT)

/* It is need clear flags because client group records can be find in the package */
SELECT @INSERTED_ROWCOUNT = 0, @UPDATED_ROWCOUNT = 0
END
IF EXISTS(SELECT * FROM @EVENTGROUP WHERE client = 1)
BEGIN
/* updating client event group records by hashavalue*/
UPDATE G
SET
firsteventdate = CASE WHEN sync.firsteventdate &lt; g.firsteventdate THEN sync.firsteventdate ELSE g.firsteventdate END
,lasteventdate = CASE WHEN sync.lasteventdate &gt; g.lasteventdate THEN sync.lasteventdate ELSE g.lasteventdate END
FROM APM.CSEVENTGROUP g
JOIN @EVENTGROUP sync ON sync.hashvalue = g.hashvalue AND sync.client = 1

/*Permit number of affected records*/
SET @UPDATED_ROWCOUNT = @@ROWCOUNT

/* Insert new server event group which are not found by hashvalue */
INSERT APM.CSEVENTGROUP (
firsteventdate
,lasteventdate
,hashvalue
,description
,sourceid
)
SELECT DISTINCT
sync.firsteventdate
,sync.lasteventdate
,sync.hashvalue
,sync.description
,s.SourceId
FROM
@EVENTGROUP sync
JOIN APM.Source AS s ON s.source = sync.source
WHERE
sync.client = 1 AND NOT EXISTS (SELECT * FROM APM.CSEVENTGROUP WHERE (hashvalue = sync.hashvalue))
SET @INSERTED_ROWCOUNT = @@ROWCOUNT

/* Log about inserted records for verbal log mode */
IF @TRACELEVEL = 4
BEGIN
SELECT @MESSAGE = MESSAGE FROM APM.MESSAGES WHERE ID = 50024
RAISERROR (@MESSAGE, 0, 1, @INSERTED_ROWCOUNT, 'CSEVENTGROUP') WITH NOWAIT;
END

/* Number of records from package */
SELECT @CHANGED_ROWCOUNT = COUNT(*) FROM @EVENTGROUP WHERE client = 1

/* Calculate not affected packages records which are not processing */
/* It is also need to add not affected records from previos processing (server event group)*/
SET @ROWNOTAFFECTED = @ROWNOTAFFECTED + @CHANGED_ROWCOUNT - (@INSERTED_ROWCOUNT + @UPDATED_ROWCOUNT)
END
END TRY
BEGIN CATCH
IF (@@TRANCOUNT &gt; 0)
ROLLBACK TRAN

SELECT
@ERRORNUMBER = ERROR_NUMBER()
,@ERRORSEVERITY = ERROR_SEVERITY()
,@ERRORSTATE = ERROR_STATE()
,@ERRORLINE = ERROR_LINE()
,@ERRORPROCEDURE = ISNULL(ERROR_PROCEDURE(), '-')
,@ERRORMESSAGETEXT = ERROR_MESSAGE()

SET @ERRORIND = 1
END CATCH

IF @XMLDOCHANDLE IS NOT NULL
EXEC sp_xml_removedocument @XMLDOCHANDLE

-- report error if any
IF (@ERRORIND = 1)
BEGIN
DECLARE @ADJUSTEDERRORSEVERITY int

SET @ADJUSTEDERRORSEVERITY = CASE
WHEN @ERRORSEVERITY = 2601 OR @ERRORSEVERITY = 2627 THEN 0
WHEN @ERRORSEVERITY &gt; 18 THEN 18
ELSE @ERRORSEVERITY
END

SELECT @ERROR_MESSAGE = message FROM APM.Messages WHERE id = 50004
RAISERROR (@ERROR_MESSAGE, @ADJUSTEDERRORSEVERITY, 1
,@ERRORNUMBER
,@ERRORSEVERITY
,@ERRORSTATE
,@ERRORPROCEDURE
,@ERRORLINE
,@ERRORMESSAGETEXT
)
END
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.PCProcess_sync'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.PCProcess_sync AS RETURN 1')
END
GO
/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: PCProcess_sync */
/* USED IN: Synchronization PCProcess table. Call by Intercept Reporting Services */
/* INPUT PARAMETERS: */
/* @OBJECTKEYXML - xml package syncronization data */
/* @TRACELEVEL - trace level. Reserved. */
/* OUTPUT PARAMETERS: */
/* @ROWNOTAFFECTED - number of records from package which haven't been */
/* synchronized.Reserved. */
/* Note: */
/* If there are records which have not been transferred that they have been already */
/* transferred from other SEVIEWER database earlier. Any other reason will cause a */
/* exception at an insert */
/************************************************************************************/
ALTER PROCEDURE APM.PCProcess_sync
@OBJECTKEYXML ntext,
@TRACELEVEL int,
@ROWNOTAFFECTED int output
AS
BEGIN
SET NOCOUNT ON

DECLARE
@ERRORIND bit
,@ERRORMESSAGE nvarchar(max)
,@ERRORNUMBER int
,@ERRORSEVERITY int
,@ERRORSTATE int
,@ERRORLINE int
,@ERRORPROCEDURE nvarchar(256)
,@ERRORMESSAGETEXT nvarchar(max)

SET @ERRORIND = 0

BEGIN TRY

SET @ROWNOTAFFECTED = 0

DECLARE
@EXECRESULT int
,@XMLDOCHANDLE int
,@ERROR_MESSAGE nvarchar(max)

EXEC @EXECRESULT = sp_xml_preparedocument @XMLDOCHANDLE OUTPUT, @OBJECTKEYXML
IF @EXECRESULT &lt;&gt; 0
BEGIN
SELECT @ERROR_MESSAGE = message FROM APM.messages WHERE id = 50002
RAISERROR(@ERROR_MESSAGE, 16, 1, 'PCProcess_sync', @EXECRESULT)
END

DECLARE @PCPROCESS TABLE (
id int IDENTITY(1,1)
,process nvarchar(255) collate database_default
,extratype int
,extrainfo nvarchar(255) collate database_default
,hashvalue nvarchar(50) collate database_default
)

----Fill table from package
INSERT @PCPROCESS (
process
,extratype
,extrainfo
,hashvalue
)
SELECT
process
,extratype
,extrainfo
,hashvalue
FROM OPENXML(@XMLDOCHANDLE, 'rows/row', 2) WITH (
process nvarchar(255)
,extratype int
,extrainfo nvarchar(255)
,hashvalue nvarchar(50) ) xml

EXEC sp_xml_removedocument @XMLDOCHANDLE

SET @XMLDOCHANDLE = NULL

--remove duplicates by hashvalue
Delete pr1
from @PCPROCESS pr1
join @PCPROCESS pr2 on pr1.id &gt; pr2.id and pr1.hashvalue = pr2.hashvalue

UPDATE pr
SET process = sync.process
,extratype = sync.extratype
,extrainfo = sync.extrainfo
FROM APM.PCProcess pr
JOIN @PCPROCESS sync ON sync.hashvalue = pr.hashvalue

INSERT APM.pcprocess (process, extratype, extrainfo, hashvalue)
SELECT DISTINCT sync.process, sync.extratype, sync.extrainfo, sync.hashvalue
FROM @PCPROCESS sync
WHERE NOT EXISTS (SELECT * FROM APM.PCProcess WHERE (hashvalue = sync.hashvalue))

END TRY
BEGIN CATCH
IF (@@TRANCOUNT &gt; 0)
ROLLBACK TRAN

SELECT
@ERRORNUMBER = ERROR_NUMBER()
,@ERRORSEVERITY = ERROR_SEVERITY()
,@ERRORSTATE = ERROR_STATE()
,@ERRORLINE = ERROR_LINE()
,@ERRORPROCEDURE = ISNULL(ERROR_PROCEDURE(), '-')
,@ERRORMESSAGETEXT = ERROR_MESSAGE()

SET @ERRORIND = 1
END CATCH

IF @XMLDOCHANDLE IS NOT NULL
EXEC sp_xml_removedocument @XMLDOCHANDLE

-- report error if any
IF (@ERRORIND = 1)
BEGIN
DECLARE @ADJUSTEDERRORSEVERITY int

SET @ADJUSTEDERRORSEVERITY = CASE
WHEN @ERRORSEVERITY = 2601 OR @ERRORSEVERITY = 2627 THEN 0
WHEN @ERRORSEVERITY &gt; 18 THEN 18
ELSE @ERRORSEVERITY
END

SELECT @ERROR_MESSAGE = message FROM APM.Messages WHERE id = 50004
RAISERROR (@ERROR_MESSAGE, @ADJUSTEDERRORSEVERITY, 1
,@ERRORNUMBER
,@ERRORSEVERITY
,@ERRORSTATE
,@ERRORPROCEDURE
,@ERRORLINE
,@ERRORMESSAGETEXT
)
END
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.PCDescription_sync'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.PCDescription_sync AS RETURN 1')
END
GO
/*********************************************************************************** */
/* OBJECT: Stored Procedure */
/* NAME: PCDescription_sync */
/* USED IN: Synchronization PCDescription table. Call by Intercept Reporting Services */
/* INPUT PARAMETERS: */
/* @OBJECTKEYXML - xml package syncronization data */
/* @TRACELEVEL - trace level. Reserved. */
/* OUTPUT PARAMETERS: */
/* @ROWNOTAFFECTED - number of records from package which haven't been */
/* synchronized.Reserved. */
/* Note: */
/* If there are records which have not been transferred that they have been already */
/* transferred from other SEVIEWER database earlier. Any other reason will cause a */
/* exception at an insert */
/*************************************************************************************/
ALTER PROCEDURE APM.PCDescription_sync
@OBJECTKEYXML ntext,
@TRACELEVEL int,
@ROWNOTAFFECTED int output
AS
BEGIN
SET NOCOUNT ON

DECLARE
@ERRORIND bit
,@ERRORMESSAGE nvarchar(max)
,@ERRORNUMBER int
,@ERRORSEVERITY int
,@ERRORSTATE int
,@ERRORLINE int
,@ERRORPROCEDURE nvarchar(256)
,@ERRORMESSAGETEXT nvarchar(max)

SET @ERRORIND = 0

BEGIN TRY

DECLARE
@EXECRESULT int
,@XMLDOCHANDLE int
,@ERROR_MESSAGE nvarchar(max)

SET @ROWNOTAFFECTED = 0

EXEC @EXECRESULT = sp_xml_preparedocument @XMLDOCHANDLE OUTPUT, @OBJECTKEYXML
IF @EXECRESULT &lt;&gt; 0
BEGIN
SELECT @ERROR_MESSAGE = message FROM APM.messages WHERE id = 50002
RAISERROR(@ERROR_MESSAGE, 16, 1, 'PCDescription_sync', @EXECRESULT)
END

DECLARE @PCDESCRIPTION TABLE (
name nvarchar(255) collate database_default NOT NULL
,description nvarchar(max) collate database_default NULL
)

----Fill table from package
INSERT @PCDESCRIPTION (
name
,description
)
SELECT
Name
,Description
FROM OPENXML(@XMLDOCHANDLE, 'rows/row', 2) WITH (
name nvarchar(255)
,description nvarchar(max) ) xml

EXEC sp_xml_removedocument @XMLDOCHANDLE

SET @XMLDOCHANDLE = NULL

--------------sync description---------
UPDATE d
SET Name = sync.name, Description = sync.description
FROM APM.PCDescription d
JOIN @PCDESCRIPTION sync ON sync.name = d.Name

INSERT APM.pcdescription (name, description)
SELECT DISTINCT sync.name, sync.description
FROM @PCDESCRIPTION sync
WHERE NOT EXISTS (SELECT * FROM APM.PCDescription WHERE (name = sync.name))

END TRY
BEGIN CATCH
IF (@@TRANCOUNT &gt; 0)
ROLLBACK TRAN

SELECT
@ERRORNUMBER = ERROR_NUMBER()
,@ERRORSEVERITY = ERROR_SEVERITY()
,@ERRORSTATE = ERROR_STATE()
,@ERRORLINE = ERROR_LINE()
,@ERRORPROCEDURE = ISNULL(ERROR_PROCEDURE(), '-')
,@ERRORMESSAGETEXT = ERROR_MESSAGE()

SET @ERRORIND = 1
END CATCH

IF @XMLDOCHANDLE IS NOT NULL
EXEC sp_xml_removedocument @XMLDOCHANDLE

-- report error if any
IF (@ERRORIND = 1)
BEGIN
DECLARE @ADJUSTEDERRORSEVERITY int

SET @ADJUSTEDERRORSEVERITY = CASE
WHEN @ERRORSEVERITY = 2601 OR @ERRORSEVERITY = 2627 THEN 0
WHEN @ERRORSEVERITY &gt; 18 THEN 18
ELSE @ERRORSEVERITY
END

SELECT @ERROR_MESSAGE = message FROM APM.Messages WHERE id = 50004
RAISERROR (@ERROR_MESSAGE, @ADJUSTEDERRORSEVERITY, 1
,@ERRORNUMBER
,@ERRORSEVERITY
,@ERRORSTATE
,@ERRORPROCEDURE
,@ERRORLINE
,@ERRORMESSAGETEXT
)
END
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.PMCREATEEVENTTRACES'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.PMCREATEEVENTTRACES AS RETURN 1')
END
GO
/**************************************************************************************************/
/* PROCEDURE PMCREATEEVENTTRACES */
/* Description: */
/* It create trace and event traces. */
/* Warning: It use temporary table #RESULT(EventId int). Therefore it is need to */
/* create #RESULT table before call procedure */
/* */
/* Input parameters: */
/* @DATA - XML OBJECT VIEW */
/* @CLIENT - 0: server events 1:client events */
/**************************************************************************************************/
ALTER PROCEDURE [APM].[PMCREATEEVENTTRACES]
@CLIENT bit
,@DATA nvarchar(MAX)
AS
SET NOCOUNT ON

DECLARE
@TRACEOUTPUT TABLE (NEWTRACE int, PMSTATUS nvarchar(max))

--create trace package
INSERT APM.PMTRACE (PMSTATUS)
OUTPUT INSERTED.PMTRACEID, INSERTED.PMSTATUS INTO @TRACEOUTPUT
SELECT DISTINCT r.PMSTATUS FROM #STATUSTABLE r

IF @@ROWCOUNT = 0
RAISERROR(N'#STATUSTABLE is empty. Imposible created trace.', 0, 1) WITH NOWAIT

-- update data
IF @DATA IS NOT NULL
UPDATE t
SET t.DATA = @DATA
FROM APM.PMTRACE t
JOIN @TRACEOUTPUT nt ON T.pmtraceId = nt.NEWTRACE

--server trace
IF @CLIENT = 0
--Fill server event trace
--Join with Event table is need because these events can be deleted by grooming
INSERT APM.PMSERVEREVENTTRACE(EVENTID, PMTRACEID)
SELECT e.EVENTID, t.NEWTRACE
FROM #STATUSTABLE AS st
JOIN APM.EVENT (NOLOCK) AS e ON e.EVENTID = st.EVENTID
JOIN @TRACEOUTPUT t ON t.PMSTATUS = st.PMSTATUS

IF @CLIENT = 1
--Fill client event trace
--Join with Event table is need because these events can be deleted by grooming
INSERT APM.PMCLIENTEVENTTRACE(CSEVENTID, PMTRACEID)
SELECT e.CSEVENTID, t.NEWTRACE
FROM #STATUSTABLE AS st
JOIN APM.CSEVENT (NOLOCK) AS e ON e.CSEVENTID = st.EVENTID
JOIN @TRACEOUTPUT t ON t.PMSTATUS = st.PMSTATUS
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.ServerEvent_sync'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.ServerEvent_sync AS RETURN 1')
END
GO
/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: ServerEvent_sync */
/* USED IN: Synchronization server event. */
/* Call by Intercept Reporting Services */
/* INPUT PARAMETERS: */
/* @OBJECTKEYXML - xml package syncronization data */
/* @TRACELEVEL - trace level. Reserved. */
/* OUTPUT PARAMETERS: */
/* @ROWNOTAFFECTED - number of records from package which haven't been */
/* synchronized. */
/************************************************************************************/
ALTER PROCEDURE [APM].[ServerEvent_sync]
@OBJECTKEYXML ntext
,@DATABASEID int
,@TRACELEVEL int
,@ROWNOTAFFECTED int output
AS
BEGIN
SET NOCOUNT ON

DECLARE
@ERRORIND bit
,@ERRORMESSAGE nvarchar(max)
,@ERRORNUMBER int
,@ERRORSEVERITY int
,@ERRORSTATE int
,@ERRORLINE int
,@ERRORPROCEDURE nvarchar(256)
,@ERRORMESSAGETEXT nvarchar(max)

SET @ERRORIND = 0

BEGIN TRY

SET @ROWNOTAFFECTED = 0

DECLARE
@EXECRESULT int
,@XMLDOCHANDLE int
,@INSERTED_ROWCOUNT int
,@CHANGED_ROWCOUNT int
,@ERROR_MESSAGE nvarchar(max)

--allocate memory for xml package
EXEC @EXECRESULT = sp_xml_preparedocument @XMLDOCHANDLE OUTPUT, @OBJECTKEYXML
IF @EXECRESULT &lt;&gt; 0
BEGIN
SELECT @ERROR_MESSAGE = message FROM APM.messages WHERE id = 50002
RAISERROR(@ERROR_MESSAGE, 16, 1, 'ServerEvent_sync', @EXECRESULT)
END

-----temporary table variable for the keeping xml package
DECLARE @EVENT TABLE (
grouphash nvarchar(50) collate database_default
,rootnodename nvarchar(255) collate database_default
,rootfunction nvarchar(255) collate database_default
,component nvarchar(255) collate database_default
,source nvarchar(255) collate database_default
,eventduration decimal(35,0)
,machinename nvarchar(255) collate database_default
,utceventdate datetime
,eventclasstype nvarchar(50) collate database_default
,aspect nvarchar(50) collate database_default
,username nvarchar(255) collate database_default
,exceptionclass nvarchar(255) collate database_default
,description nvarchar(255) collate database_default
,category nvarchar(255) collate database_default
,rowguid nvarchar(15) collate database_default
,seviewerdbid int
,sevieweregid int
,heavylight int
,pmstatus tinyint
)

---- parse and insert xml package to the temporary table variabale
INSERT @EVENT (
grouphash
,rootnodename
,rootfunction
,component
,source
,eventduration
,machinename
,utceventdate
,eventclasstype
,aspect
,username
,exceptionclass
,description
,category
,rowguid
,sevieweregid
,heavylight
,pmstatus
)
SELECT
grouphash
,rootnodename
,rootfunction
,component
,source
,eventduration
,machinename
,utceventdate
,eventclasstype
,aspect
,username
,exceptionclass
,description
,category
,rowguid
,sevieweregid
,heavylight
,pmstatus
FROM OPENXML(@XMLDOCHANDLE, 'rows/row', 2) WITH (
grouphash nvarchar(50)
,rootnodename nvarchar(255)
,rootfunction nvarchar(255)
,component nvarchar(255)
,source nvarchar(255)
,eventduration decimal(35,0)
,machinename nvarchar(255)
,utceventdate datetime
,eventclasstype nvarchar(50)
,aspect nvarchar(50)
,username nvarchar(255)
,exceptionclass nvarchar(255)
,description nvarchar(255)
,category nvarchar(255)
,rowguid nvarchar(15)
,sevieweregid int -------- reference to the seviewer event group ---
,heavylight int
,pmstatus tinyint
) xml

--free memory of xml package
EXEC sp_xml_removedocument @XMLDOCHANDLE

SET @XMLDOCHANDLE = NULL

----------sync event------------

-------- update reference to the seviewer database -------
UPDATE @EVENT SET seviewerdbid = @DATABASEID

-------- sync Users table---------------
INSERT Users (name)
SELECT DISTINCT sync.username FROM @EVENT sync
WHERE NOT EXISTS(SELECT u.name FROM APM.Users u WHERE sync.username = u.name)
AND sync.username IS NOT NULL AND sync.username &lt;&gt; ''

DECLARE @ALLAPPID int
DECLARE @NEWMACHINES TABLE (machineId int)

----- machine can be removed using "Remove computers wizard" so it is need synchronize machines ----
INSERT APM.MACHINE (MACHINE) OUTPUT INSERTED.MACHINEID INTO @NEWMACHINES
SELECT DISTINCT machinename FROM @EVENT e
WHERE NOT EXISTS (SELECT * FROM APM.machine m (NOLOCK) WHERE m.machine = e.machinename)

IF EXISTS(SELECT * FROM @NEWMACHINES)
BEGIN
IF @ALLAPPID IS NULL
SELECT @ALLAPPID = APPLICATIONID FROM APM.APPLICATION (NOLOCK) WHERE APPLICATION = N'All'
---- it is need to create the links with 'All' application group for new sources
INSERT APM.APPLICATIONSOURCEMACHINE
( APPLICATIONID ,
SOURCEID ,
MACHINEID
)
SELECT
@ALLAPPID
,s.SourceId
,m.machineId
FROM
APM.SOURCE (NOLOCK) AS s
CROSS JOIN @NEWMACHINES as m
WHERE
NOT EXISTS
(
SELECT * FROM APM.APPLICATIONSOURCEMACHINE (NOLOCK) AS a
WHERE a.SOURCEID = s.sourceId AND a.APPLICATIONID = @ALLAPPID AND m.machineId = a.machineid
)
END

----- sources can be removed using "Remove applications wizard" so it is need synchronize sources ----
DECLARE @NEWSOURCES TABLE (sourceid int)

INSERT APM.SOURCE (SOURCE) OUTPUT INSERTED.SOURCEID INTO @NEWSOURCES
SELECT DISTINCT source FROM @EVENT e
WHERE NOT EXISTS (SELECT * FROM APM.source s (NOLOCK) WHERE s.source = e.source)

IF EXISTS(SELECT * FROM @NEWSOURCES)
BEGIN
IF @ALLAPPID IS NULL
SELECT @ALLAPPID = APPLICATIONID FROM APM.APPLICATION (NOLOCK) WHERE APPLICATION = N'All'
---- it is need to create the links with 'All' application group for new machines
INSERT APM.APPLICATIONSOURCEMACHINE
( APPLICATIONID ,
SOURCEID ,
MACHINEID
)
SELECT
@ALLAPPID
,s.sourceid
,m.machineId
FROM
APM.MACHINE (NOLOCK) AS m
CROSS JOIN @NEWSOURCES as s
WHERE
NOT EXISTS
(
SELECT * FROM APM.APPLICATIONSOURCEMACHINE (NOLOCK) AS a
WHERE a.SOURCEID = s.sourceid AND a.APPLICATIONID = @ALLAPPID AND m.MACHINEid = a.machineid
)
END


-------------- sync event table ------------------

-- temporary table for traces. It will contains event id of the new events.
CREATE TABLE #STATUSTABLE(EVENTID int, PMSTATUS tinyint)

INSERT EVENT (
eventgroupid
,sourceid
,eventduration
,machineid
,utceventdate
,eventclasstype
,rootnodename
,aspect
,exceptionclass
,description
,category
,rowguid
,seviewerdbid
,sevieweregid
,heavylight
,pmstatus
)
OUTPUT INSERTED.EVENTID, INSERTED.PMSTATUS
INTO #STATUSTABLE
SELECT
g.eventgroupid
,s.sourceid
,sync.eventduration
,m.MACHINEID
,sync.utceventdate
,sync.eventclasstype
,sync.rootnodename
,sync.aspect
,sync.exceptionclass
,sync.description
,sync.category
,sync.rowguid
,sync.seviewerdbid
,sync.sevieweregid
,sync.heavylight
,pmstatus
FROM
@EVENT sync
JOIN APM.source s (NOLOCK) ON s.source = sync.source
JOIN APM.EventGroup g (NOLOCK) ON g.hashvalue = sync.grouphash
JOIN APM.MACHINE m (NOLOCK) ON m.machine = sync.machinename
WHERE NOT EXISTS(SELECT * FROM event e (NOLOCK) WHERE sync.rowguid = e.rowguid)
--should be the same order between RowGuid and primary key of the Event table
ORDER BY CAST(SUBSTRING(sync.rowguid, CHARINDEX('-', rowguid) + 1, LEN(rowguid)) AS INT)

SET @INSERTED_ROWCOUNT = @@ROWCOUNT

--Create event traces for server events
EXEC APM.PMCREATEEVENTTRACES 0, NULL

-----------sync event with username------------------
UPDATE e SET
e.userid = u.userid
FROM
APM.event e
JOIN @EVENT sync ON sync.rowguid = e.rowguid
JOIN Users u (NOLOCK) ON sync.username = u.Name

INSERT EVENTDETAIL
(
EventId
,Name
,[Value]
,[ValueType]
)
SELECT
e.EventId
,'COMPONENT'
,sync.component
,'PM'
FROM
@EVENT AS sync
JOIN APM.Event AS e (NOLOCK) ON sync.rowguid = e.rowguid

INSERT EVENTDETAIL
(
EventId
,Name
,[Value]
,[ValueType]
)
SELECT
e.EventId
,'ROOTFUNCTION'
,sync.rootfunction
,'PM'
FROM
@EVENT AS sync
JOIN APM.Event AS e (NOLOCK) ON sync.rowguid = e.rowguid

SELECT @CHANGED_ROWCOUNT = COUNT(*) FROM @EVENT
SET @ROWNOTAFFECTED = @CHANGED_ROWCOUNT - @INSERTED_ROWCOUNT

END TRY
BEGIN CATCH
IF (@@TRANCOUNT &gt; 0)
ROLLBACK TRAN

SELECT
@ERRORNUMBER = ERROR_NUMBER()
,@ERRORSEVERITY = ERROR_SEVERITY()
,@ERRORSTATE = ERROR_STATE()
,@ERRORLINE = ERROR_LINE()
,@ERRORPROCEDURE = ISNULL(ERROR_PROCEDURE(), '-')
,@ERRORMESSAGETEXT = ERROR_MESSAGE()

SET @ERRORIND = 1
END CATCH

IF @XMLDOCHANDLE IS NOT NULL
EXEC sp_xml_removedocument @XMLDOCHANDLE

-- report error if any
IF (@ERRORIND = 1)
BEGIN
DECLARE @ADJUSTEDERRORSEVERITY int

SET @ADJUSTEDERRORSEVERITY = CASE
WHEN @ERRORSEVERITY = 2601 OR @ERRORSEVERITY = 2627 THEN 0
WHEN @ERRORSEVERITY &gt; 18 THEN 18
ELSE @ERRORSEVERITY
END

SELECT @ERROR_MESSAGE = message FROM APM.Messages WHERE id = 50004
RAISERROR (@ERROR_MESSAGE, @ADJUSTEDERRORSEVERITY, 1
,@ERRORNUMBER
,@ERRORSEVERITY
,@ERRORSTATE
,@ERRORPROCEDURE
,@ERRORLINE
,@ERRORMESSAGETEXT
)
END
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.PerformanceNode_sync'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.PerformanceNode_sync AS RETURN 1')
END
GO
ALTER PROCEDURE [APM].[PerformanceNode_sync]
@OBJECTKEYXML ntext,
@TRACELEVEL int,
@ROWNOTAFFECTED int output
AS
BEGIN
SET NOCOUNT ON

DECLARE
@ERRORIND bit
,@ERRORMESSAGE nvarchar(max)
,@ERRORNUMBER int
,@ERRORSEVERITY int
,@ERRORSTATE int
,@ERRORLINE int
,@ERRORPROCEDURE nvarchar(256)
,@ERRORMESSAGETEXT nvarchar(max)

SET @ERRORIND = 0

BEGIN TRY

SET @ROWNOTAFFECTED = 0

DECLARE
@EXECRESULT int
,@XMLDOCHANDLE int
,@ERROR_MESSAGE nvarchar(max)
,@INSERTED_ROWCOUNT int
,@CHANGED_ROWCOUNT int
,@MESSAGE nvarchar(max)

EXEC @EXECRESULT = sp_xml_preparedocument @XMLDOCHANDLE OUTPUT, @OBJECTKEYXML
IF @EXECRESULT &lt;&gt; 0
BEGIN
SELECT @ERROR_MESSAGE = message FROM APM.messages WHERE id = 50002
RAISERROR(@ERROR_MESSAGE, 16, 1, 'PerformanceNode_sync', @EXECRESULT)
END


DECLARE @PERFORMANCENODE TABLE (
eventrowguid nvarchar(15) collate database_default
,description nvarchar(255) collate database_default
,functionname nvarchar(255) collate database_default
,duration decimal(35,0)
,hashcode nvarchar(255) collate database_default
,entryid int
,rowguid nvarchar(15) collate database_default
,client int
,isheaviestnode bit
)


INSERT @PERFORMANCENODE (
eventrowguid
,description
,functionname
,duration
,hashcode
,entryid
,rowguid
,client
,isheaviestnode
)
SELECT
xml.eventrowguid
,xml.description
,xml.functionname
,xml.duration
,xml.hashcode
,xml.entryid
,xml.rowguid
,xml.client
,xml.isheaviestnode
FROM
OPENXML(@XMLDOCHANDLE, 'rows/row', 2) WITH (
eventrowguid nvarchar(15)
,description nvarchar(255)
,functionname nvarchar(255)
,duration decimal(35,0)
,hashcode nvarchar(255)
,entryid int
,rowguid nvarchar(15)
,client int
,isheaviestnode bit
) xml


EXEC sp_xml_removedocument @XMLDOCHANDLE

SET @XMLDOCHANDLE = NULL

----------sync performanceNode------------

/* updating server or client performance */

IF EXISTS(SELECT * FROM @PERFORMANCENODE WHERE client = 0)
BEGIN
/* server performance */

INSERT APM.PerformanceNode (
eventid
,description
,functionname
,duration
,hashcode
,entryid
,rowguid
,isheaviestnode
)
SELECT
e.eventid
,sync.description
,sync.functionname
,sync.duration
,sync.hashcode
,sync.entryid
,sync.rowguid
,sync.isheaviestnode
FROM
@PERFORMANCENODE sync
JOIN APM.Event e (NOLOCK) ON e.rowguid = sync.eventrowguid
WHERE
sync.client = 0 AND NOT EXISTS(SELECT * FROM APM.performanceNode (NOLOCK) WHERE rowguid = sync.rowguid)
SET @INSERTED_ROWCOUNT = @@ROWCOUNT

IF @TRACELEVEL = 4
BEGIN
SELECT @MESSAGE = MESSAGE FROM APM.MESSAGES WHERE ID = 50024
RAISERROR (@MESSAGE, 0, 1, @INSERTED_ROWCOUNT, 'PerformanceNode') WITH NOWAIT;
END

SELECT @CHANGED_ROWCOUNT = COUNT(*) FROM @PERFORMANCENODE WHERE client = 0

SET @ROWNOTAFFECTED = @CHANGED_ROWCOUNT - @INSERTED_ROWCOUNT
SELECT @INSERTED_ROWCOUNT = 0
END
IF EXISTS(SELECT * FROM @PERFORMANCENODE WHERE client = 1)
BEGIN
/* client performance */

INSERT APM.csheaviestresource (
cseventid
,name
,duration
,rowguid
,isheaviestnode
)
SELECT
e.cseventid
,sync.description
,sync.duration
,sync.rowguid
,sync.isheaviestnode

FROM
@PERFORMANCENODE sync
JOIN APM.CSEvent e (NOLOCK) ON e.rowguid = sync.eventrowguid
WHERE
sync.client = 1 AND NOT EXISTS(SELECT * FROM APM.csheaviestresource (NOLOCK) WHERE rowguid = sync.rowguid)
SET @INSERTED_ROWCOUNT = @@ROWCOUNT

IF @TRACELEVEL = 4
BEGIN
SELECT @MESSAGE = MESSAGE FROM APM.MESSAGES WHERE ID = 50024
RAISERROR (@MESSAGE, 0, 1, @INSERTED_ROWCOUNT, 'csheaviestresource') WITH NOWAIT;
END

SELECT @CHANGED_ROWCOUNT = COUNT(*) FROM @PERFORMANCENODE WHERE client = 1

SET @ROWNOTAFFECTED = @ROWNOTAFFECTED + @CHANGED_ROWCOUNT - @INSERTED_ROWCOUNT
END
END TRY
BEGIN CATCH
IF (@@TRANCOUNT &gt; 0)
ROLLBACK TRAN

SELECT
@ERRORNUMBER = ERROR_NUMBER()
,@ERRORSEVERITY = ERROR_SEVERITY()
,@ERRORSTATE = ERROR_STATE()
,@ERRORLINE = ERROR_LINE()
,@ERRORPROCEDURE = ISNULL(ERROR_PROCEDURE(), '-')
,@ERRORMESSAGETEXT = ERROR_MESSAGE()

SET @ERRORIND = 1
END CATCH

IF @XMLDOCHANDLE IS NOT NULL
EXEC sp_xml_removedocument @XMLDOCHANDLE

-- report error if any
IF (@ERRORIND = 1)
BEGIN
DECLARE @ADJUSTEDERRORSEVERITY int

SET @ADJUSTEDERRORSEVERITY = CASE
WHEN @ERRORSEVERITY = 2601 OR @ERRORSEVERITY = 2627 THEN 0
WHEN @ERRORSEVERITY &gt; 18 THEN 18
ELSE @ERRORSEVERITY
END

SELECT @ERROR_MESSAGE = message FROM APM.Messages WHERE id = 50004
RAISERROR (@ERROR_MESSAGE, @ADJUSTEDERRORSEVERITY, 1
,@ERRORNUMBER
,@ERRORSEVERITY
,@ERRORSTATE
,@ERRORPROCEDURE
,@ERRORLINE
,@ERRORMESSAGETEXT
)
END
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.ExceptionNode_sync'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.ExceptionNode_sync AS RETURN 1')
END
GO
ALTER PROCEDURE APM.ExceptionNode_sync
@OBJECTKEYXML ntext
,@TRACELEVEL int
,@ROWNOTAFFECTED int output
AS
BEGIN
SET NOCOUNT ON

DECLARE
@ERRORIND bit
,@ERRORMESSAGE nvarchar(max)
,@ERRORNUMBER int
,@ERRORSEVERITY int
,@ERRORSTATE int
,@ERRORLINE int
,@ERRORPROCEDURE nvarchar(256)
,@ERRORMESSAGETEXT nvarchar(max)

SET @ERRORIND = 0

BEGIN TRY

SET @ROWNOTAFFECTED = 0

DECLARE
@EXECRESULT int
,@XMLDOCHANDLE int
,@ERROR_MESSAGE nvarchar(max)
,@INSERTED_ROWCOUNT int
,@CHANGED_ROWCOUNT int
,@MESSAGE nvarchar(max)

EXEC @EXECRESULT = sp_xml_preparedocument @XMLDOCHANDLE OUTPUT, @OBJECTKEYXML
IF @EXECRESULT &lt;&gt; 0
BEGIN
SELECT @ERROR_MESSAGE = message FROM APM.messages WHERE id = 50002
RAISERROR(@ERROR_MESSAGE, 16, 1, 'exceptionnode_sync', @EXECRESULT)
END

DECLARE @EXCEPTIONNODE TABLE (
eventrowguid nvarchar(15) collate database_default
,eventAction nvarchar(255) collate database_default
,description nvarchar(255) collate database_default
,exceptionmessage nvarchar(255) collate database_default
,exceptionclass nvarchar(255) collate database_default
,functionname nvarchar(255) collate database_default
,modulename nvarchar(255) collate database_default
,linenumber bigint
,entryid int
,hashcode nvarchar(255) collate database_default
,rowguid nvarchar(15) collate database_default
,client int
)

SET @ROWNOTAFFECTED = 0

INSERT @EXCEPTIONNODE (
eventrowguid
,eventAction
,description
,exceptionmessage
,exceptionclass
,functionname
,modulename
,linenumber
,entryid
,hashcode
,rowguid
,client
)
SELECT
eventrowguid
,eventaction
,description
,exceptionmessage
,exceptionclass
,functionname
,modulename
,linenumber
,entryid
,hashcode
,rowguid
,client
FROM OPENXML(@XMLDOCHANDLE, 'rows/row', 2) WITH (
eventrowguid nvarchar(15)
,eventaction nvarchar(255)
,description nvarchar(255)
,exceptionmessage nvarchar(255)
,exceptionclass nvarchar(255)
,functionname nvarchar(255)
,modulename nvarchar(255)
,linenumber bigint
,entryid int
,hashcode nvarchar(255)
,rowguid nvarchar(15)
,client int
) xml

EXEC sp_xml_removedocument @XMLDOCHANDLE

SET @XMLDOCHANDLE = NULL

----------sync exceptionNode------------
IF EXISTS(SELECT * FROM @EXCEPTIONNODE WHERE client = 0)
BEGIN
/* server exception */

INSERT APM.ExceptionNode (
eventid
,exceptionmessage
,exceptionclass
,functionname
,modulename
,linenumber
,description
,hashcode
,entryid
,rowguid
)
SELECT
e.eventid
,sync.exceptionmessage
,sync.exceptionclass
,sync.functionname
,sync.modulename
,sync.linenumber
,sync.description
,sync.hashcode
,sync.entryid
,sync.rowguid
FROM
@EXCEPTIONNODE sync
JOIN APM.Event e ON e.rowguid = sync.eventrowguid
WHERE sync.client = 0 AND NOT EXISTS(SELECT * FROM APM.ExceptionNode WHERE rowguid = sync.rowguid)
SET @INSERTED_ROWCOUNT = @@ROWCOUNT

IF @TRACELEVEL = 4
BEGIN
SELECT @MESSAGE = MESSAGE FROM APM.MESSAGES WHERE ID = 50024
RAISERROR (@MESSAGE, 0, 1, @INSERTED_ROWCOUNT, 'ExceptionNode') WITH NOWAIT;
END

SELECT @CHANGED_ROWCOUNT = COUNT(*) FROM @EXCEPTIONNODE where client = 0

SET @ROWNOTAFFECTED = @CHANGED_ROWCOUNT - @INSERTED_ROWCOUNT
SET @INSERTED_ROWCOUNT = 0
END

IF EXISTS(SELECT * FROM @EXCEPTIONNODE WHERE client = 1)
BEGIN
/* client exception */
INSERT APM.CSEXEVENT (
cseventid
,action
,exmessage
,extype
,exfunction
,rowguid
)
SELECT
e.cseventid
,sync.eventAction
,sync.exceptionmessage
,sync.exceptionclass
,sync.functionname
,sync.rowguid
FROM
@EXCEPTIONNODE sync
JOIN APM.CSEvent e ON e.rowguid = sync.eventrowguid
WHERE sync.client = 1 AND NOT EXISTS(SELECT * FROM APM.ExceptionNode WHERE rowguid = sync.rowguid)
SET @INSERTED_ROWCOUNT = @@ROWCOUNT

IF @TRACELEVEL = 4
BEGIN
SELECT @MESSAGE = MESSAGE FROM APM.MESSAGES WHERE ID = 50024
RAISERROR (@MESSAGE, 0, 1, @INSERTED_ROWCOUNT, 'CSEXEVENT') WITH NOWAIT;
END

SELECT @CHANGED_ROWCOUNT = COUNT(*) FROM @EXCEPTIONNODE WHERE client = 1
SET @ROWNOTAFFECTED = @ROWNOTAFFECTED + @CHANGED_ROWCOUNT - @INSERTED_ROWCOUNT

END
END TRY
BEGIN CATCH
IF (@@TRANCOUNT &gt; 0)
ROLLBACK TRAN

SELECT
@ERRORNUMBER = ERROR_NUMBER()
,@ERRORSEVERITY = ERROR_SEVERITY()
,@ERRORSTATE = ERROR_STATE()
,@ERRORLINE = ERROR_LINE()
,@ERRORPROCEDURE = ISNULL(ERROR_PROCEDURE(), '-')
,@ERRORMESSAGETEXT = ERROR_MESSAGE()

SET @ERRORIND = 1
END CATCH

IF @XMLDOCHANDLE IS NOT NULL
EXEC sp_xml_removedocument @XMLDOCHANDLE

-- report error if any
IF (@ERRORIND = 1)
BEGIN
DECLARE @ADJUSTEDERRORSEVERITY int

SET @ADJUSTEDERRORSEVERITY = CASE
WHEN @ERRORSEVERITY = 2601 OR @ERRORSEVERITY = 2627 THEN 0
WHEN @ERRORSEVERITY &gt; 18 THEN 18
ELSE @ERRORSEVERITY
END

SELECT @ERROR_MESSAGE = message FROM APM.Messages WHERE id = 50004
RAISERROR (@ERROR_MESSAGE, @ADJUSTEDERRORSEVERITY, 1
,@ERRORNUMBER
,@ERRORSEVERITY
,@ERRORSTATE
,@ERRORPROCEDURE
,@ERRORLINE
,@ERRORMESSAGETEXT
)
END
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.PerfHourly_sync'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.PerfHourly_sync AS RETURN 1')
END
GO
ALTER PROCEDURE [APM].[PerfHourly_sync]
@OBJECTKEYXML ntext,
@DATABASEID int,
@TRACELEVEL int,
@ROWNOTAFFECTED int output
AS
BEGIN
SET NOCOUNT ON

DECLARE
@ERRORIND bit
,@ERRORMESSAGE nvarchar(max)
,@ERRORNUMBER int
,@ERRORSEVERITY int
,@ERRORSTATE int
,@ERRORLINE int
,@ERRORPROCEDURE nvarchar(256)
,@ERRORMESSAGETEXT nvarchar(max)

SET @ERRORIND = 0

BEGIN TRY

SET @ROWNOTAFFECTED = 0

DECLARE
@EXECRESULT int
,@XMLDOCHANDLE int
,@ERROR_MESSAGE nvarchar(max)
,@INSERTED_ROWCOUNT int
,@UPDATED_ROWCOUNT int
,@CHANGED_ROWCOUNT int
,@CURSOR_OPENED bit

SELECT @CHANGED_ROWCOUNT = 0, @UPDATED_ROWCOUNT = 0, @INSERTED_ROWCOUNT = 0, @CHANGED_ROWCOUNT = 0

EXEC @EXECRESULT = sp_xml_preparedocument @XMLDOCHANDLE OUTPUT, @OBJECTKEYXML
IF @EXECRESULT &lt;&gt; 0
BEGIN
SELECT @ERROR_MESSAGE = message FROM APM.messages WHERE id = 50002
RAISERROR(@ERROR_MESSAGE, 16, 1, 'PerfHourly_sync', @EXECRESULT)
END

DECLARE @PERFHOURLY TABLE (
type nvarchar(255) collate database_default
,machinename nvarchar(255) collate database_default
,source nvarchar(255) collate database_default
,pcprocessHash nvarchar(50) collate database_default
,is_state int
,utcdate datetime
,averagevalue float
,minvalue float
,maxvalue float
,samplecount float
,sumvalue float
,packagecounter int
,hashvalue nvarchar(50) collate database_default
,inserted bit
)

INSERT @PERFHOURLY (
type
,machinename
,source
,pcprocessHash
,is_state
,utcdate
,averagevalue
,minvalue
,maxvalue
,samplecount
,sumvalue
,packagecounter
,hashvalue
)
SELECT
type
,machinename
,source
,pcprocessHash
,is_state
,utcdate
,averagevalue
,minvalue
,maxvalue
,samplecount
,sumvalue
,packagecounter
,hashvalue
FROM OPENXML(@XMLDOCHANDLE, 'rows/row', 2) WITH (
type nvarchar(255)
,machinename nvarchar(255)
,source nvarchar(255)
,pcprocesshash nvarchar(50)
,is_state int
,utcdate datetime
,averagevalue float
,minvalue float
,maxvalue float
,samplecount float
,sumvalue float
,packagecounter int
,hashvalue nvarchar(50)
) xml

SET @CHANGED_ROWCOUNT = @@ROWCOUNT

EXEC sp_xml_removedocument @XMLDOCHANDLE

SET @XMLDOCHANDLE = NULL

DECLARE @ALLAPPID int
DECLARE @NEWMACHINES TABLE (machineId int)

------- machine can be removed using "Remove computers wizard" so it is need synchronize machines ----
INSERT APM.MACHINE (MACHINE) OUTPUT INSERTED.MACHINEID INTO @NEWMACHINES
SELECT DISTINCT machinename FROM @PERFHOURLY p
WHERE NOT EXISTS (SELECT * FROM APM.machine m (NOLOCK) WHERE m.machine = p.machinename) AND p.machinename is NOT null

IF EXISTS(SELECT * FROM @NEWMACHINES)
BEGIN
IF @ALLAPPID IS NULL
SELECT @ALLAPPID = APPLICATIONID FROM APM.APPLICATION (NOLOCK) WHERE APPLICATION = N'All'
---- it is need to create the links with 'All' application group for new sources
INSERT APM.APPLICATIONSOURCEMACHINE
( APPLICATIONID ,
SOURCEID ,
MACHINEID
)
SELECT
@ALLAPPID
,s.SourceId
,m.machineId
FROM
APM.SOURCE (NOLOCK) AS s
CROSS JOIN @NEWMACHINES as m
WHERE
NOT EXISTS
(
SELECT * FROM APM.APPLICATIONSOURCEMACHINE (NOLOCK) AS a
WHERE a.SOURCEID = s.sourceId AND a.APPLICATIONID = @ALLAPPID AND m.machineId = a.machineid
)
END

----- sources can be removed using "Remove applications wizard" so it is need synchronize sources ----
DECLARE @NEWSOURCES TABLE (sourceid int)

----- sources can be removed using "Remove applications wizard" so it is need synchronize sources ----
INSERT APM.SOURCE (SOURCE) OUTPUT INSERTED.SOURCEID INTO @NEWSOURCES
SELECT DISTINCT source FROM @PERFHOURLY p
WHERE NOT EXISTS (SELECT * FROM APM.source s (NOLOCK) WHERE s.source = p.source) AND p.source is NOT null

IF EXISTS(SELECT * FROM @NEWSOURCES)
BEGIN
IF @ALLAPPID IS NULL
SELECT @ALLAPPID = APPLICATIONID FROM APM.APPLICATION (NOLOCK) WHERE APPLICATION = N'All'
---- it is need to create the links with 'All' application group for new machines
INSERT APM.APPLICATIONSOURCEMACHINE
( APPLICATIONID ,
SOURCEID ,
MACHINEID
)
SELECT
@ALLAPPID
,s.sourceid
,m.machineId
FROM
APM.MACHINE (NOLOCK) AS m
CROSS JOIN @NEWSOURCES as s
WHERE
NOT EXISTS
(
SELECT * FROM APM.APPLICATIONSOURCEMACHINE (NOLOCK) AS a
WHERE a.SOURCEID = s.sourceid AND a.APPLICATIONID = @ALLAPPID AND m.MACHINEid = a.machineid
)
END

UPDATE sync
SET sync.inserted = 1
FROM @PERFHOURLY sync
WHERE NOT EXISTS(SELECT * FROM APM.PerfHourly p WHERE p.hashvalue = sync.hashvalue)

IF EXISTS(SELECT * FROM @PERFHOURLY sync WHERE sync.inserted = 1)
BEGIN
INSERT perfHourly(
pctypeid
,machineid
,sourceid
,pcprocessId
,is_state
,utcdate
,averagevalue
,minvalue
,maxvalue
,samplecount
,sumvalue
,packagecounter
,hashvalue
)
SELECT
t.pctypeid
,m.machineid
,s.sourceId
,pr.pcprocessId
,sync.is_state
,sync.utcdate
,sync.averagevalue
,sync.minvalue
,sync.maxvalue
,sync.samplecount
,sync.sumvalue
,sync.packagecounter
,sync.hashvalue
FROM
@PERFHOURLY sync
JOIN APM.Machine m ON m.machine = sync.machinename
JOIN APM.PCType t ON t.type = sync.type
LEFT JOIN APM.Source s ON s.source = sync.source
LEFT JOIN APM.PCProcess Pr ON PR.hashvalue = sync.pcprocessHash
WHERE
sync.inserted = 1

SET @INSERTED_ROWCOUNT = @@ROWCOUNT
END

IF EXISTS(SELECT * FROM @PERFHOURLY sync WHERE sync.inserted is null)
BEGIN
UPDATE p
SET
p.minvalue = CASE WHEN sync.minvalue &lt; p.minvalue THEN sync.minvalue ELSE p.minvalue END
,p.maxvalue = CASE WHEN sync.maxvalue &gt; p.maxvalue THEN sync.maxvalue ELSE p.maxvalue END
,p.samplecount = p.samplecount + sync.samplecount
,p.sumvalue = p.sumvalue + sync.sumvalue
,p.packagecounter = p.packagecounter + sync.packagecounter
,p.averagevalue = p.sumvalue / p.samplecount
FROM
APM.PerfHourly p
JOIN @PERFHOURLY sync ON sync.hashvalue = p.hashvalue
JOIN APM.Machine m ON m.machine = sync.machinename
JOIN APM.PCType t ON t.type = sync.type
LEFT JOIN APM.Source s ON s.source = sync.source
LEFT JOIN APM.PCProcess Pr ON PR.hashvalue = sync.pcprocessHash
WHERE sync.inserted IS NULL

SET @UPDATED_ROWCOUNT = @@ROWCOUNT
END

SET @ROWNOTAFFECTED = @CHANGED_ROWCOUNT - (@INSERTED_ROWCOUNT + @UPDATED_ROWCOUNT)

END TRY
BEGIN CATCH
IF (@@TRANCOUNT &gt; 0)
ROLLBACK TRAN

SELECT
@ERRORNUMBER = ERROR_NUMBER()
,@ERRORSEVERITY = ERROR_SEVERITY()
,@ERRORSTATE = ERROR_STATE()
,@ERRORLINE = ERROR_LINE()
,@ERRORPROCEDURE = ISNULL(ERROR_PROCEDURE(), '-')
,@ERRORMESSAGETEXT = ERROR_MESSAGE()

SET @ERRORIND = 1
END CATCH

IF @XMLDOCHANDLE IS NOT NULL
EXEC sp_xml_removedocument @XMLDOCHANDLE

-- report error if any
IF (@ERRORIND = 1)
BEGIN
DECLARE @ADJUSTEDERRORSEVERITY int

SET @ADJUSTEDERRORSEVERITY = CASE
WHEN @ERRORSEVERITY = 2601 OR @ERRORSEVERITY = 2627 THEN 0
WHEN @ERRORSEVERITY &gt; 18 THEN 18
ELSE @ERRORSEVERITY
END

SELECT @ERROR_MESSAGE = message FROM APM.Messages WHERE id = 50004
RAISERROR (@ERROR_MESSAGE, @ADJUSTEDERRORSEVERITY, 1
,@ERRORNUMBER
,@ERRORSEVERITY
,@ERRORSTATE
,@ERRORPROCEDURE
,@ERRORLINE
,@ERRORMESSAGETEXT
)
END
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.CheckDatabaseId'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.CheckDatabaseId AS RETURN 1')
END
GO
/* Procedure check database unique identificator and return error codes: */
/* 0 : Success. Database is synhronized with SEViewer database */
/* 1 : Error. Database is not synhronized with SEViewer database */
/* 2 : Error. Database is partialy synhronized with SEViewer database */
/* 3 : Error. Database is new */
ALTER PROCEDURE APM.CheckDatabaseId
@DBGUID uniqueidentifier
AS
BEGIN
DECLARE @ERROR int

SET @ERROR = 0

IF NOT EXISTS(SELECT * FROM APM.SEVIewerDB SV (NOLOCK) WHERE SV.DatabaseId = @DBGUID)
BEGIN
IF NOT EXISTS(SELECT * FROM APM.TASKS (NOLOCK))
BEGIN
SET @ERROR = 3
GOTO QUIT
END
IF EXISTS(SELECT * FROM APM.TASKS t (NOLOCK) WHERE t.SEVIewerDBId IS NULL)
BEGIN
SET @ERROR = 1
GOTO QUIT
END
END

IF EXISTS(SELECT * FROM APM.TASKS t (NOLOCK) WHERE t.SEVIewerDBId IS NULL)
BEGIN
SET @ERROR = 2
GOTO QUIT
END

QUIT:
RETURN @ERROR
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.CheckAndCreateDatabaseId'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.CheckAndCreateDatabaseId AS RETURN 1')
END
GO
/**************************************************************************************************/
/* Procedure check database unique identificator and find or create internal database identifier */
/* Procedure return error code: */
/* 0 : Success. Database is synhronized with SEViewer database */
/* 1 : Error. Database is not synhronized with SEViewer database */
/* 2 : Error. Database is partialy synhronized with SEViewer database */
/**************************************************************************************************/
/* Parameters: */
/* @DBGUID unique identificator */
/* @SEVIEWERURL unique identificator */
/* @DBGUID unique identificator */
ALTER PROCEDURE APM.CheckAndCreateDatabaseId
@DBGUID uniqueidentifier
,@SEVIEWERURL NVARCHAR(255)
,@TRACELEVEL INT
,@DBID int OUTPUT
AS
BEGIN
DECLARE @ERROR int

EXECUTE @ERROR = APM.CheckDatabaseId @DBGUID

SELECT @DBID = SEVIewerDBId FROM APM.SEVIewerDB SV (NOLOCK) WHERE SV.DatabaseId = @DBGUID
IF @@ROWCOUNT = 0
BEGIN
INSERT APM.SEVIEWERDB(DatabaseId, Address) Values(@DBGUID, @SEVIEWERURL)
SET @DBID = SCOPE_IDENTITY()
END

RETURN @ERROR
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.Config_sync'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.Config_sync AS RETURN 1')
END
GO
alter PROCEDURE APM.Config_sync
@OBJECTKEYXML ntext
,@TRACELEVEL INT
,@ROWNOTAFFECTED int output
AS
BEGIN
SET NOCOUNT ON

DECLARE
@ERRORIND bit
,@ERRORMESSAGE nvarchar(max)
,@ERRORNUMBER int
,@ERRORSEVERITY int
,@ERRORSTATE int
,@ERRORLINE int
,@ERRORPROCEDURE nvarchar(256)
,@ERRORMESSAGETEXT nvarchar(max)

SET @ERRORIND = 0

BEGIN TRY

DECLARE
@EXECRESULT int
,@XMLDOCHANDLE int
,@ERROR_MESSAGE nvarchar(max)
,@UPDATED_ROWCOUNT int
,@CHANGEDROWCOUNT int

SET @ROWNOTAFFECTED = 0

EXEC @EXECRESULT = sp_xml_preparedocument @XMLDOCHANDLE OUTPUT, @OBJECTKEYXML
IF @EXECRESULT &lt;&gt; 0
BEGIN
SELECT @ERROR_MESSAGE = message FROM APM.messages WHERE id = 50002
RAISERROR(@ERROR_MESSAGE, 16, 1, 'Config_sync', @EXECRESULT)
END

DECLARE @CONFIG TABLE (
configname nvarchar(50) NOT NULL
,configvalue nvarchar(max) NULL
,databaseid int
)

INSERT @CONFIG (
configname
,configvalue
,databaseid
)
SELECT
configname
,configvalue
,databaseid
FROM OPENXML(@XMLDOCHANDLE, 'rows/row', 2) WITH (
configname nvarchar(50)
,configvalue nvarchar(max)
,databaseid int) xml

EXEC sp_xml_removedocument @XMLDOCHANDLE

SET @XMLDOCHANDLE = NULL

UPDATE sv SET
Address = sync.configvalue
FROM
APM.SEViewerDb sv
JOIN @CONFIG sync ON sv.seviewerdbid = sync.databaseid AND sync.configname = 'SEVIEWERADDRESS'
SET @UPDATED_ROWCOUNT = @@ROWCOUNT

SELECT @CHANGEDROWCOUNT = COUNT(*) FROM @CONFIG WHERE configname = 'SEVIEWERADDRESS'

SET @ROWNOTAFFECTED = @CHANGEDROWCOUNT - @UPDATED_ROWCOUNT
END TRY
BEGIN CATCH
IF (@@TRANCOUNT &gt; 0)
ROLLBACK TRAN

SELECT
@ERRORNUMBER = ERROR_NUMBER()
,@ERRORSEVERITY = ERROR_SEVERITY()
,@ERRORSTATE = ERROR_STATE()
,@ERRORLINE = ERROR_LINE()
,@ERRORPROCEDURE = ISNULL(ERROR_PROCEDURE(), '-')
,@ERRORMESSAGETEXT = ERROR_MESSAGE()

SET @ERRORIND = 1
END CATCH

IF @XMLDOCHANDLE IS NOT NULL
EXEC sp_xml_removedocument @XMLDOCHANDLE

-- report error if any
IF (@ERRORIND = 1)
BEGIN
DECLARE @ADJUSTEDERRORSEVERITY int

SET @ADJUSTEDERRORSEVERITY = CASE
WHEN @ERRORSEVERITY = 2601 OR @ERRORSEVERITY = 2627 THEN 0
WHEN @ERRORSEVERITY &gt; 18 THEN 18
ELSE @ERRORSEVERITY
END
SELECT @ERROR_MESSAGE = message FROM APM.Messages WHERE id = 50004
RAISERROR (@ERROR_MESSAGE, @ADJUSTEDERRORSEVERITY, 1
,@ERRORNUMBER
,@ERRORSEVERITY
,@ERRORSTATE
,@ERRORPROCEDURE
,@ERRORLINE
,@ERRORMESSAGETEXT
)
END
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.PageEvent_sync'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.PageEvent_sync AS RETURN 1')
END
GO
/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: PageEvent_sync */
/* USED IN: Intercept reporting Service. Fill content information for the csm */
/* performance events. Internal stored procedure */
/* INPUT PARAMETERS: */
/* @XMLDOCHANDLE - memory handle (from sp_xml_preparedocument) */
/* @TRACELEVEL - trace flag (4 - diagnostic message will be generated */
/************************************************************************************/
ALTER PROCEDURE APM.PageEvent_sync
@XMLDOCHANDLE int
,@TRACELEVEL int
AS
BEGIN
SET NOCOUNT ON

DECLARE
@INSERTED_ROWCOUNT int
,@MESSAGE nvarchar(max)

DECLARE @PAGEEVENT TABLE (
event_rowguid nvarchar(15) collate database_default
,networktime decimal (35,0)
,servertime decimal (35,0)
,domtime decimal (35,0)
,peripheraltime decimal (35,0)
,onloadtime decimal (35,0)
,totaltime decimal (35,0)
,totalsize bigint
,latency bigint
,utcdate datetime
,SourceName nvarchar (255) collate database_default
)


INSERT @PAGEEVENT (
event_rowguid
,networktime
,servertime
,domtime
,peripheraltime
,onloadtime
,totaltime
,totalsize
,latency
,utcdate
,SourceName
)
SELECT
event_rowguid
,networktime
,servertime
,domtime
,peripheraltime
,onloadtime
,totaltime
,totalsize
,latency
,utcdate
,SourceName
FROM OPENXML(@XMLDOCHANDLE, 'rows/row/pageevent') WITH (
event_rowguid nvarchar(15) '../@rowguid'
,networktime decimal (35,0)
,servertime decimal (35,0)
,domtime decimal (35,0)
,peripheraltime decimal (35,0)
,onloadtime decimal (35,0)
,totaltime decimal (35,0)
,totalsize bigint
,latency bigint
,utcdate datetime '../@utceventdate'
,sourceName nvarchar (255) '../@source'
,client int '../@client'
) xml
WHERE xml.client = 2
-- Fill CSPageEvent table--------
INSERT APM.CSPageEvent (
cseventid
,networktime
,servertime
,domtime
,peripheraltime
,onloadtime
,totaltime
,totalsize
,latency
,utcdate
,sourceid
)
SELECT
e.cseventid
,sync.networktime
,sync.servertime
,sync.domtime
,sync.peripheraltime
,sync.onloadtime
,sync.totaltime
,sync.totalsize
,sync.latency
,sync.utcdate
,s.SourceId
FROM
@PAGEEVENT sync
JOIN APM.csevent e ON sync.event_rowguid = e.rowguid
JOIN APM.source s ON s.source = sync.SourceName

SET @INSERTED_ROWCOUNT = @@ROWCOUNT

IF @TRACELEVEL = 4
BEGIN
SELECT @MESSAGE = MESSAGE FROM APM.MESSAGES WHERE ID = 50024
RAISERROR (@MESSAGE, 0, 1, @INSERTED_ROWCOUNT, 'CSPageEvent') WITH NOWAIT;
END


-- Fill Periphial and Periphial Detail table--------
DECLARE @PERIPHIAL TABLE (
event_rowguid nvarchar(15) collate database_default
,type nvarchar (50) collate database_default
,totalsize bigint
,totaltime decimal (35,0)
,htmlSize bigint
)

INSERT INTO @PERIPHIAL
(
event_rowguid
,type
,totalsize
,totaltime
,htmlSize
)
SELECT
event_rowguid
,type
,totalsize
,totaltime
,htmlSize


FROM OPENXML(@XMLDOCHANDLE, 'rows/row/peripheral/row', 2) WITH (
event_rowguid nvarchar(15) '../../@rowguid'
,type nvarchar (50) '@type'
,totalsize bigint '@totalsize'
,totaltime decimal (35,0) '@totaltime'
,htmlSize bigint '../@htmlsize'
,client int '../../@client'
) xml
WHERE xml.client = 2

DECLARE @PERIPHIALDETAIL TABLE (
event_rowguid nvarchar(15) collate database_default
,type nvarchar (50) collate database_default
,domain nvarchar (255) collate database_default
,path nvarchar (255) collate database_default
,size bigint
,detail_totaltime decimal (35,0)
)


INSERT INTO @PERIPHIALDETAIL
(
event_rowguid
,type
,domain
,path
,size
,detail_totaltime
)
SELECT
event_rowguid
,type
,domain
,path
,size
,detail_totaltime
FROM OPENXML(@XMLDOCHANDLE, 'rows/row/peripheral/row/row', 2) WITH (
event_rowguid nvarchar(15) '../../../@rowguid'
,type nvarchar (50) '../@type'
,domain nvarchar (255) '@domain'
,path nvarchar (255) '@path'
,size bigint '@size'
,detail_totaltime decimal (35,0) '@totaltime'
,client int '../../../@client'
) xml
WHERE xml.client = 2 AND xml.size &gt; 0

-- Fill summary content information
INSERT APM.csperipheral
(
cseventid
,type
,totalsize
,totaltime
)
SELECT
e.cseventid
,sync.type
,sync.totalsize
,sync.totaltime
FROM
@PERIPHIAL sync
JOIN
APM.csevent e ON sync.event_rowguid = e.rowguid
WHERE sync.totalsize &gt; 0

SET @INSERTED_ROWCOUNT = @@ROWCOUNT

IF @TRACELEVEL = 4
BEGIN
SELECT @MESSAGE = MESSAGE FROM APM.MESSAGES WHERE ID = 50024
RAISERROR (@MESSAGE, 0, 1, @INSERTED_ROWCOUNT, 'csperipheral') WITH NOWAIT;
END

-- Fill html size
INSERT APM.csperipheral
(
cseventid
,type
,totalsize
)
SELECT DISTINCT
e.cseventid
,N'html'
,sync.htmlSize
FROM
@PERIPHIAL sync
JOIN
csevent e ON sync.event_rowguid = e.rowguid

SET @INSERTED_ROWCOUNT = @@ROWCOUNT

IF @TRACELEVEL = 4
BEGIN
SELECT @MESSAGE = MESSAGE FROM APM.MESSAGES WHERE ID = 50024
RAISERROR (@MESSAGE, 0, 1, @INSERTED_ROWCOUNT, 'csperipheral {html}') WITH NOWAIT;
END

-- Fill detail content information
INSERT APM.csperipheraldetail
(
csperipheralid
,domain
,path
,size
,totaltime
)
SELECT
p.csperipheralid
,sync.domain
,sync.path
,sync.size
,sync.detail_totaltime
FROM
@PERIPHIALDETAIL sync
JOIN
APM.csevent e ON sync.event_rowguid = e.rowguid
JOIN
APM.csperipheral p ON e.cseventid = p.cseventid AND sync.type = p.type

SET @INSERTED_ROWCOUNT = @@ROWCOUNT

IF @TRACELEVEL = 4
BEGIN
SELECT @MESSAGE = MESSAGE FROM APM.MESSAGES WHERE ID = 50024
RAISERROR (@MESSAGE, 0, 1, @INSERTED_ROWCOUNT, 'csperipheraldetail') WITH NOWAIT;
END
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.AjaxCall_sync'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.AjaxCall_sync AS RETURN 1')
END
GO
ALTER PROCEDURE APM.AjaxCall_sync
@XMLDOCHANDLE int
,@PATH nvarchar(100)
,@TRACELEVEL int
AS
BEGIN
SET NOCOUNT ON

DECLARE
@MESSAGE nvarchar(max)
,@RECORDCOUNT int


--------- Fill Ajax call --------

DECLARE @AJAXCALL TABLE (
ajax_call_id int identity(1,1)
,event_rowguid nvarchar(15) collate database_default
,uri nvarchar (255) collate database_default
,networktime decimal (35,0)
,servertime decimal (35,0)
,totaltime decimal (35,0)
,requestsize bigint
,responsesize bigint
,responsetime decimal (35,0)
,handlertime decimal (35,0)
,latency bigint
,utcdate datetime
,SourceName nvarchar (255) collate database_default
)


INSERT INTO @AJAXCALL
(
event_rowguid
,uri
,networktime
,servertime
,totaltime
,requestsize
,responsesize
,responsetime
,handlertime
,latency
,utcdate
,SourceName
)
SELECT
event_rowguid
,uri
,networktime
,servertime
,totaltime
,requestsize
,responsesize
,responsetime
,handlertime
,latency
,utcdate
,SourceName
FROM OPENXML(@XMLDOCHANDLE, @PATH) WITH (
event_rowguid nvarchar(15) '../../@rowguid'
,uri nvarchar (255)
,networktime decimal (35,0)
,servertime decimal (35,0)
,totaltime decimal (35,0)
,requestsize bigint
,responsesize bigint
,responsetime decimal (35,0)
,handlertime decimal (35,0) '../@handlertime'
,latency bigint
,utcdate datetime '../../@utceventdate'
,sourceName nvarchar (255) '../../@source'
) xml

INSERT APM.csajax
(
cseventid
,uri
,networktime
,servertime
,totaltime
,requestsize
,responsesize
,responsetime
,synchronous
,latency
,utcdate
,sourceid
,IsHeaviestNode
)
SELECT
e.cseventid
,sync.uri
,sync.networktime
,sync.servertime
,sync.totaltime
,sync.requestsize
,sync.responsesize
,sync.responsetime
,CASE WHEN handlertime IS NULL THEN 1 ELSE 0 END
,sync.latency
,sync.utcdate
,s.SourceId
,CASE
WHEN sync.ajax_call_id = (SELECT TOP(1) ajax_call_id FROM @AJAXCALL AS a WHERE sync.event_rowguid = a.event_rowguid ORDER BY TotalTime DESC, ajax_call_id)
THEN 1
ELSE 0
END
FROM
@AJAXCALL sync
JOIN
APM.csevent e ON sync.event_rowguid = e.rowguid
JOIN APM.source s ON s.source = sync.SourceName

SELECT @RECORDCOUNT = @@ROWCOUNT

IF @TRACELEVEL = 4
BEGIN
SELECT @MESSAGE = MESSAGE FROM APM.MESSAGES WHERE ID = 50024
RAISERROR (@MESSAGE, 0, 1, @RECORDCOUNT, 'csajax') WITH NOWAIT;
END

---Find Async ajax call-----------

IF EXISTS(SELECT * FROM @AJAXCALL WHERE handlertime IS NOT NULL)
BEGIN
INSERT APM.csasyncajax
(
cseventid
,totaltime
,handlertime
)
SELECT
e.cseventid
,sync.totaltime
,sync.handlertime
FROM
@AJAXCALL sync
JOIN
APM.csevent e ON sync.event_rowguid = e.rowguid
WHERE
sync.handlertime IS NOT NULL

SELECT @RECORDCOUNT = @@ROWCOUNT

IF @TRACELEVEL = 4
BEGIN
SELECT @MESSAGE = MESSAGE FROM APM.MESSAGES WHERE ID = 50024
RAISERROR (@MESSAGE, 0, 1, @RECORDCOUNT, 'csasyncajax') WITH NOWAIT;
END
END
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.JScriptEvent_sync'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.JScriptEvent_sync AS RETURN 1')
END
GO
ALTER PROCEDURE APM.JScriptEvent_sync
@XMLDOCHANDLE int
,@TRACELEVEL int
AS
BEGIN
SET NOCOUNT ON

DECLARE
@INSERTED_ROWCOUNT int
,@MESSAGE nvarchar(max)

DECLARE @SCRIPTEVENT TABLE (
event_rowguid nvarchar(15) collate database_default
,action nvarchar(255) collate database_default
,totaltime nvarchar(255) collate database_default
,utcdate datetime
,SourceName nvarchar (255) collate database_default
)


INSERT @SCRIPTEVENT (
event_rowguid
,action
,totaltime
,utcdate
,SourceName
)
SELECT
event_rowguid
,action
,totaltime
,utcdate
,SourceName
FROM OPENXML(@XMLDOCHANDLE, 'rows/row/jscript') WITH (
event_rowguid nvarchar(15) '../@rowguid'
,action nvarchar(255)
,totaltime decimal (35,0)
,utcdate datetime '../@utceventdate'
,sourceName nvarchar (255) '../@source'
) xml

-- Fill CSJSCRIPTEVENT table--------
INSERT APM.csjscriptevent (
cseventid
,action
,totaltime
,utcdate
,sourceid
)
SELECT
e.cseventid
,sync.action
,sync.totaltime
,sync.utcdate
,s.SourceId
FROM
@SCRIPTEVENT sync
JOIN APM.csevent e ON sync.event_rowguid = e.rowguid
JOIN APM.source s ON s.source = sync.SourceName

SET @INSERTED_ROWCOUNT = @@ROWCOUNT

IF @TRACELEVEL = 4
BEGIN
SELECT @MESSAGE = MESSAGE FROM APM.MESSAGES WHERE ID = 50024
RAISERROR (@MESSAGE, 0, 1, @INSERTED_ROWCOUNT, 'csjscriptevent') WITH NOWAIT;
END
END
GO



IF (OBJECTPROPERTY(OBJECT_ID('APM.ClientEvent_sync'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.ClientEvent_sync AS RETURN 1')
END
GO
/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: ClientEvent_sync */
/* USED IN: Synchronization client event. */
/* Call by Intercept Reporting Services */
/* INPUT PARAMETERS: */
/* @OBJECTKEYXML - xml package syncronization data */
/* @TRACELEVEL - trace level. Reserved. */
/* OUTPUT PARAMETERS: */
/* @ROWNOTAFFECTED - number of records from package which haven't been */
/* synchronized. */
/************************************************************************************/
ALTER PROCEDURE [APM].[ClientEvent_sync]
@OBJECTKEYXML ntext
,@DATABASEID int
,@TRACELEVEL int
,@ROWNOTAFFECTED int output
AS
BEGIN
SET NOCOUNT ON

DECLARE
@MESSAGE nvarchar(max)
,@RECORDCOUNT int

DECLARE
@ERRORIND bit
,@ERRORMESSAGE nvarchar(max)
,@ERRORNUMBER int
,@ERRORSEVERITY int
,@ERRORSTATE int
,@ERRORLINE int
,@ERRORPROCEDURE nvarchar(256)
,@ERRORMESSAGETEXT nvarchar(max)

SET @ERRORIND = 0

BEGIN TRY

SET @ROWNOTAFFECTED = 0

DECLARE
@EXECRESULT int
,@XMLDOCHANDLE int
,@INSERTED_ROWCOUNT int
,@CHANGED_ROWCOUNT int
,@ERROR_MESSAGE nvarchar(max)

--allocate memory for xml package
EXEC @EXECRESULT = sp_xml_preparedocument @XMLDOCHANDLE OUTPUT, @OBJECTKEYXML
IF @EXECRESULT &lt;&gt; 0
BEGIN
SELECT @ERROR_MESSAGE = message FROM APM.messages WHERE id = 50002
RAISERROR(@ERROR_MESSAGE, 16, 1, 'ClientEvent_sync', @EXECRESULT)
END

-----temporary table variable for the keeping xml package
DECLARE @EVENT TABLE (
grouphash nvarchar(50) collate database_default
,source nvarchar(255) collate database_default
,machinename nvarchar(255) collate database_default
,utceventdate datetime
,eventclasstype nvarchar(50) collate database_default
,eventclass nvarchar(50) collate database_default
,description nvarchar(255) collate database_default
,ip nvarchar(50) collate database_default
,subnetc nvarchar(50) collate database_default
,pageuri nvarchar(255) collate database_default
,browser nvarchar(255) collate database_default
,userName nvarchar(255) collate database_default
,rowguid nvarchar(15) collate database_default
,seviewerdbid int
,sevieweregid int
,client int
,pmstatus tinyint
,category nvarchar(50) collate database_default
,rootnodename nvarchar(255) collate database_default
,rootfunction nvarchar(255) collate database_default
)

---- parse and insert xml package to the temporary table variabale
INSERT @EVENT (
grouphash
,source
,machinename
,utceventdate
,eventclasstype
,eventclass
,description
,ip
,subnetc
,pageuri
,browser
,userName
,rowguid
,sevieweregid
,client
,pmstatus
,category
,rootnodename
,rootfunction
)
SELECT
grouphash
,source
,machinename
,utceventdate
,eventclasstype
,eventclass
,description
,ip
,subnetc
,pageuri
,browser
,username
,rowguid
,sevieweregid
,client
,pmstatus
,category
,rootnodename
,rootfunction
FROM OPENXML(@XMLDOCHANDLE, 'rows/row') WITH (
grouphash nvarchar(50)
,source nvarchar(255)
,machinename nvarchar(255)
,utceventdate datetime
,eventclasstype nvarchar(50)
,eventclass nvarchar(50)
,description nvarchar(255)
,ip nvarchar(50)
,subnetc nvarchar(50)
,pageuri nvarchar(255)
,browser nvarchar(255)
,username nvarchar(255)
,rowguid nvarchar(15)
,sevieweregid int
,client int
,pmstatus tinyint
,category nvarchar(50)
,rootnodename nvarchar(255)
,rootfunction nvarchar(255)
) xml

SELECT @RECORDCOUNT = @@ROWCOUNT

--- Trace about package size
IF @TRACELEVEL = 4
BEGIN
SELECT @MESSAGE = MESSAGE FROM APM.MESSAGES WHERE ID = 50024
RAISERROR (@MESSAGE, 0, 1, @RECORDCOUNT, '@EVENT') WITH NOWAIT;
END

UPDATE @EVENT SET seviewerdbid = @DATABASEID

DECLARE @ALLAPPID int
DECLARE @NEWMACHINES TABLE (machineId int)

----- machine can be removed using "Remove computers wizard" so it is need synchronize machines ----
INSERT APM.MACHINE (MACHINE) OUTPUT INSERTED.MACHINEID INTO @NEWMACHINES
SELECT DISTINCT machinename FROM @EVENT e
WHERE NOT EXISTS (SELECT * FROM APM.machine m (NOLOCK) WHERE m.machine = e.machinename)

IF EXISTS(SELECT * FROM @NEWMACHINES)
BEGIN
IF @ALLAPPID IS NULL
SELECT @ALLAPPID = APPLICATIONID FROM APM.APPLICATION (NOLOCK) WHERE APPLICATION = N'All'
---- it is need to create the links with 'All' application group for new sources
INSERT APM.APPLICATIONSOURCEMACHINE
( APPLICATIONID ,
SOURCEID ,
MACHINEID
)
SELECT
@ALLAPPID
,s.SourceId
,m.machineId
FROM
APM.SOURCE (NOLOCK) AS s
CROSS JOIN @NEWMACHINES as m
WHERE
NOT EXISTS
(
SELECT * FROM APM.APPLICATIONSOURCEMACHINE (NOLOCK) AS a
WHERE a.SOURCEID = s.sourceId AND a.APPLICATIONID = @ALLAPPID AND m.machineId = a.machineid
)
END

----- sources can be removed using "Remove applications wizard" so it is need synchronize sources ----
DECLARE @NEWSOURCES TABLE (sourceid int)

----- sources can be removed using "Remove applications wizard" so it is need synchronize sources ----
INSERT APM.SOURCE (SOURCE) OUTPUT INSERTED.SOURCEID INTO @NEWSOURCES
SELECT DISTINCT source FROM @EVENT e
WHERE NOT EXISTS (SELECT * FROM APM.source s (NOLOCK) WHERE s.source = e.source)

IF EXISTS(SELECT * FROM @NEWSOURCES)
BEGIN
IF @ALLAPPID IS NULL
SELECT @ALLAPPID = APPLICATIONID FROM APM.APPLICATION (NOLOCK) WHERE APPLICATION = N'All'
---- it is need to create the links with 'All' application group for new machines
INSERT APM.APPLICATIONSOURCEMACHINE
( APPLICATIONID ,
SOURCEID ,
MACHINEID
)
SELECT
@ALLAPPID
,s.sourceid
,m.machineId
FROM
APM.MACHINE (NOLOCK) AS m
CROSS JOIN @NEWSOURCES as s
WHERE
NOT EXISTS
(
SELECT * FROM APM.APPLICATIONSOURCEMACHINE (NOLOCK) AS a
WHERE a.SOURCEID = s.sourceid AND a.APPLICATIONID = @ALLAPPID AND m.MACHINEid = a.machineid
)
END

-------- sync Users table---------------
INSERT Users (name)
SELECT DISTINCT sync.userName FROM @EVENT sync
WHERE NOT EXISTS(SELECT u.name FROM APM.Users u WHERE sync.userName = u.name)
AND sync.userName IS NOT NULL AND sync.userName &lt;&gt; ''

-- Fill Ip table--------
INSERT APM.ip (ip, subnetc)
SELECT DISTINCT
sync.ip
,sync.subnetc
FROM
@EVENT sync
WHERE
sync.ip IS NOT NULL AND sync.ip &lt;&gt; '' AND NOT EXISTS(SELECT * FROM APM.ip ip WHERE ip.ip = sync.ip)

-- temporary table for traces. It will contains event id of the new events.
CREATE TABLE #STATUSTABLE(EVENTID int, PMSTATUS tinyint)

-- Fill CSEvent table--------
INSERT APM.CSEVENT (
cseventgroupid
,sourceid
,machineid
,utcdate
,classtype
,eventclass
,description
,ipid
,pageuri
,browser
,rowguid
,seviewerdbid
,sevieweregid
,pmstatus
)
OUTPUT INSERTED.csEventId, INSERTED.pmstatus
INTO #STATUSTABLE
SELECT
g.cseventgroupid
,s.sourceid
,m.MACHINEID
,sync.utceventdate
,sync.eventclasstype
,sync.eventclass
,sync.description
,ip.ipid
,sync.pageuri
,sync.browser
,sync.rowguid
,sync.seviewerdbid
,sync.sevieweregid -------- reference to the seviewer event group ---
,sync.pmstatus
FROM
@EVENT sync
JOIN APM.source s ON s.source = sync.source
JOIN APM.CSEventGroup g ON g.hashvalue = sync.grouphash
JOIN APM.MACHINE m ON m.machine = sync.machinename
LEFT JOIN APM.ip ip ON sync.ip = ip.ip
WHERE NOT EXISTS(SELECT * FROM APM.csevent e WHERE sync.rowguid = e.rowguid)
SET @INSERTED_ROWCOUNT = @@ROWCOUNT

--Create event traces for client events
EXEC APM.PMCREATEEVENTTRACES 1, NULL

INSERT APM.CSEVENTDETAIL
(
CSEventId
,Name
,[Value]
,[ValueType]
)
SELECT
e.CSEventId
,'CATEGORY'
,sync.category
,'PM'
FROM
@EVENT AS sync
JOIN APM.CSEvent AS e (NOLOCK) ON sync.rowguid = e.rowguid

INSERT APM.CSEVENTDETAIL
(
CSEventId
,Name
,[Value]
,[ValueType]
)
SELECT
e.CSEventId
,'ROOTNODENAME'
,sync.rootnodename
,'PM'
FROM
@EVENT AS sync
JOIN APM.CSEvent AS e (NOLOCK) ON sync.rowguid = e.rowguid

INSERT APM.CSEVENTDETAIL
(
CSEventId
,Name
,[Value]
,[ValueType]
)
SELECT
e.CSEventId
,'ROOTFUNCTION'
,sync.rootfunction
,'PM'
FROM
@EVENT AS sync
JOIN APM.CSEvent AS e (NOLOCK) ON sync.rowguid = e.rowguid

--------- trace about number of inserted records into csevent table -----------
IF @TRACELEVEL = 4
BEGIN
SELECT @MESSAGE = MESSAGE FROM APM.MESSAGES WHERE ID = 50024
RAISERROR (@MESSAGE, 0, 1, @INSERTED_ROWCOUNT, 'CSEvent') WITH NOWAIT;
END

SELECT @CHANGED_ROWCOUNT = COUNT(*) FROM @EVENT
SET @ROWNOTAFFECTED = @CHANGED_ROWCOUNT - @INSERTED_ROWCOUNT

-----------sync csevent with username------------------
UPDATE e SET
e.userid = u.userid
FROM
APM.csevent e
JOIN @EVENT sync ON sync.rowguid = e.rowguid
JOIN APM.Users u ON sync.userName = u.Name

IF EXISTS(SELECT * FROM @EVENT WHERE client = 2)
BEGIN
IF @TRACELEVEL = 4
BEGIN
SELECT @MESSAGE = MESSAGE FROM APM.MESSAGES WHERE ID = 50025
RAISERROR (@MESSAGE, 0, 1) WITH NOWAIT;
END
----exists pageevents--------
EXECUTE APM.PageEvent_sync @XMLDOCHANDLE, @TRACELEVEL
END

------ Fill ajax calls--------------
EXEC APM.AjaxCall_sync @XMLDOCHANDLE, N'rows/row/ajaxcalls/row', @TRACELEVEL

--------Check Ajax events and script events
IF EXISTS(SELECT * FROM @EVENT WHERE client = 1)
BEGIN
IF @TRACELEVEL = 4
BEGIN
SELECT @MESSAGE = MESSAGE FROM APM.MESSAGES WHERE ID = 50026
RAISERROR (@MESSAGE, 0, 1) WITH NOWAIT;
END
----Find and sync script events --------
EXEC APM.AjaxCall_sync @XMLDOCHANDLE, N'rows/row/jscript/row', @TRACELEVEL
EXECUTE APM.JScriptEvent_sync @XMLDOCHANDLE, @TRACELEVEL
END

-- Update CSEvent table with totaltime, total size and latency values
UPDATE e SET
e.TotalTime = COALESCE(p.TotalTime, COALESCE(js.TotalTime, a.TotalTime)),
e.TotalSize = COALESCE(P.TotalSize, 0) + COALESCE(a.TotalSize, 0),
e.Latency = COALESCE(p.Latency, a.Latency)
FROM
APM.csevent e
JOIN @EVENT sync ON sync.rowguid = e.rowguid
LEFT OUTER JOIN APM.CSPAGEEVENT AS p ON p.CSEventId = e.CSEventId
LEFT OUTER JOIN APM.CSJSCRIPTEVENT AS js ON js.CSEventId = e.CSEventId
OUTER APPLY
(
SELECT
SUM(a.TotalTime) AS TotalTime,
SUM(a.ResponseSize + a.REQUESTSIZE) AS TotalSize,
AVG(a.Latency) AS Latency
FROM
APM.CSAJAX AS a
WHERE
A.CSEventId = e.CSEventId
) AS a

--free memory of xml package
EXEC sp_xml_removedocument @XMLDOCHANDLE

SET @XMLDOCHANDLE = NULL

END TRY
BEGIN CATCH
IF (@@TRANCOUNT &gt; 0)
ROLLBACK TRAN

SELECT
@ERRORNUMBER = ERROR_NUMBER()
,@ERRORSEVERITY = ERROR_SEVERITY()
,@ERRORSTATE = ERROR_STATE()
,@ERRORLINE = ERROR_LINE()
,@ERRORPROCEDURE = ISNULL(ERROR_PROCEDURE(), '-')
,@ERRORMESSAGETEXT = ERROR_MESSAGE()

SET @ERRORIND = 1
END CATCH

IF @XMLDOCHANDLE IS NOT NULL
EXEC sp_xml_removedocument @XMLDOCHANDLE

-- report error if any
IF (@ERRORIND = 1)
BEGIN
DECLARE @ADJUSTEDERRORSEVERITY int

SET @ADJUSTEDERRORSEVERITY = CASE
WHEN @ERRORSEVERITY = 2601 OR @ERRORSEVERITY = 2627 THEN 0
WHEN @ERRORSEVERITY &gt; 18 THEN 18
ELSE @ERRORSEVERITY
END

SELECT @ERROR_MESSAGE = message FROM APM.Messages WHERE id = 50004
RAISERROR (@ERROR_MESSAGE, @ADJUSTEDERRORSEVERITY, 1
,@ERRORNUMBER
,@ERRORSEVERITY
,@ERRORSTATE
,@ERRORPROCEDURE
,@ERRORLINE
,@ERRORMESSAGETEXT
)
END
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.CheckConfiguration'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.CheckConfiguration AS RETURN 1')
END
GO

ALTER PROCEDURE [APM].[CheckConfiguration]
@VERSION nvarchar(15)
,@SCHEMAVERSION nvarchar(15)
,@TRACELEVEL INT
AS
BEGIN
SET NOCOUNT ON;

DECLARE
@ERROR INT

SET @ERROR = 0

IF NOT EXISTS(SELECT * FROM APM.Config WHERE ConfigName = N'DATABASE_VERSION'
AND CAST(ConfigValue AS nvarchar(15)) = @VERSION)
BEGIN
SET @ERROR = 1
GOTO QUIT
END

-- Check that schema is valid
IF NOT EXISTS(SELECT * FROM APM.Config WHERE ConfigName = N'SCHEMA_VERSION'
AND CAST(ConfigValue AS nvarchar(15)) = @SCHEMAVERSION)
BEGIN
SET @ERROR = 1
GOTO QUIT
END


QUIT:
RETURN @ERROR
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.CreateOrUpdateTaskStatus'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.CreateOrUpdateTaskStatus AS RETURN 1')
END
GO

ALTER PROCEDURE APM.CreateOrUpdateTaskStatus
@DATABASEID int
,@TASK nvarchar(50)
,@OPERATION int
,@STATUS nvarchar(50)
,@STARTED bit
,@DATE dateTime
,@LASTTIMESTAMP bigint
,@TRACELEVEL int
,@OPERATIONINDEX bigint OUTPUT
AS
BEGIN
SET NOCOUNT ON;

DECLARE
@RECORDCOUNT int

SELECT
@OPERATIONINDEX = t.LastTimeStamp
FROM
APM.Tasks t
WHERE
t.TableName = @TASK
AND t.SEViewerDbId = @DATABASEID

SELECT @RECORDCOUNT = @@ROWCOUNT

IF @RECORDCOUNT = 1
BEGIN
UPDATE
APM.Tasks
SET Status = @STATUS
,StartDate = CASE WHEN @STARTED = 1 THEN @DATE ELSE StartDate END
,EndDate = CASE WHEN @STARTED = 0 THEN @DATE ELSE EndDate END
,LastTimeStamp = CASE WHEN @STARTED = 0 THEN @LASTTIMESTAMP ELSE LastTimeStamp END
,OperationId = @OPERATION
WHERE
TableName = @TASK
AND SEViewerDbId = @DATABASEID
IF @STARTED = 0
Set @OPERATIONINDEX = @LASTTIMESTAMP
END
IF @RECORDCOUNT = 0
BEGIN
INSERT
APM.Tasks (TableName, StartDate, OperationId, LastTimeStamp, Status, SEViewerDbId)
VALUES (
@TASK
,@DATE
,@OPERATION
,0
,@STATUS
,@DATABASEID
)
SET @OPERATIONINDEX = 0
END
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.SelectAbsDateORRelative'), 'IsScalarFunction') IS NULL)
BEGIN
EXECUTE('CREATE FUNCTION APM.SelectAbsDateORRelative ()
RETURNS int
AS begin return 1 end')
END
GO

ALTER FUNCTION APM.SelectAbsDateORRelative(
@RELATIVEDATE INT,
@ABSDATE DATETIME,
--@ISENDDATE parameter defines how to return relative date
--if @ISENDDATE = 1, then appropriate date returned with 23:59 hours, otherwise it would be rounded to 00:00
@ISENDDATE BIT,
--Offset field is used to return time value in client timezone, it can be different from SQL server
@OFFSET INT) RETURNS DATETIME
AS
BEGIN
DECLARE @RESULTDATE DATETIME
-- Current time in user timezone
DECLARE @CURRENTUSERDATE DATETIME
SELECT @CURRENTUSERDATE = DATEADD(minute, @OFFSET, GETUTCDATE())

IF @RELATIVEDATE &lt;&gt; 0
BEGIN
SELECT @RESULTDATE =
CASE @RELATIVEDATE
-- This Week: First Day
WHEN 10 THEN DATEADD(d, -(DATEPART(WEEKDAY, @CURRENTUSERDATE) - 1), @CURRENTUSERDATE)
-- This Week: Last Day
WHEN 20 THEN DATEADD(d, (7 - DATEPART(WEEKDAY, @CURRENTUSERDATE)), @CURRENTUSERDATE)
-- Previous Week: First Day
WHEN 30 THEN DATEADD(WEEK, -1, DATEADD(d, -(DATEPART(WEEKDAY, @CURRENTUSERDATE) - 1), @CURRENTUSERDATE))
-- Previous Week: Last Day
WHEN 40 THEN DATEADD(WEEK, -1, DATEADD(d, (7 - DATEPART(WEEKDAY, @CURRENTUSERDATE)), @CURRENTUSERDATE))
-- This Month: First Day
WHEN 50 THEN DATEADD(DAY, -(DATEPART(DAY, @CURRENTUSERDATE) - 1), @CURRENTUSERDATE)
-- This Month: Last Day
WHEN 60 THEN DATEADD(d, -DATEPART(DAY, DATEADD(MONTH, 1, @CURRENTUSERDATE)), DATEADD(MONTH, 1, @CURRENTUSERDATE))
-- Previous Month: First Day
WHEN 70 THEN DATEADD(MONTH, -1, DATEADD(DAY, -(DATEPART(DAY, @CURRENTUSERDATE) - 1), @CURRENTUSERDATE))
-- Previous Month: Last Day
WHEN 80 THEN DATEADD(DAY, -DATEPART(DAY, @CURRENTUSERDATE), @CURRENTUSERDATE)
-- Today
WHEN 90 THEN @CURRENTUSERDATE
-- Yesterday
WHEN 100 THEN DATEADD(DAY, -1, @CURRENTUSERDATE)
-- Tomorrow
WHEN 110 THEN DATEADD(DAY, 1, @CURRENTUSERDATE)
END
--Round datetime to date, without hours
SELECT @RESULTDATE = CONVERT(NVARCHAR, @RESULTDATE, 112)

IF @ISENDDATE &gt; 0
BEGIN
--If IsEndDate parameter specified, take all day (time value equal to 23:59:59)
SELECT @RESULTDATE = DATEADD(second, -1, DATEADD(d, 1, @RESULTDATE))
IF @RESULTDATE &gt; @CURRENTUSERDATE
SELECT @RESULTDATE = DATEADD(HOUR, DATEPART(HOUR,@CURRENTUSERDATE)+1, CONVERT(NVARCHAR, @CURRENTUSERDATE, 112))
END
END
ELSE
SELECT @RESULTDATE =@ABSDATE

RETURN @RESULTDATE
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.EventDetail_sync'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.EventDetail_sync AS RETURN 1')
END
GO

ALTER PROCEDURE APM.EventDetail_sync
@OBJECTKEYXML ntext
,@TRACELEVEL INT
,@ROWNOTAFFECTED int output
AS
BEGIN
SET NOCOUNT ON

DECLARE
@ERRORIND bit
,@ERRORMESSAGE nvarchar(max)
,@ERRORNUMBER int
,@ERRORSEVERITY int
,@ERRORSTATE int
,@ERRORLINE int
,@ERRORPROCEDURE nvarchar(256)
,@ERRORMESSAGETEXT nvarchar(max)

SET @ERRORIND = 0

BEGIN TRY

DECLARE
@EXECRESULT int
,@XMLDOCHANDLE int
,@ERROR_MESSAGE nvarchar(max)
,@INSERTED_ROWCOUNT int
,@UPDATED_ROWCOUNT int
,@CHANGEDROWCOUNT int

SET @ROWNOTAFFECTED = 0

EXEC @EXECRESULT = sp_xml_preparedocument @XMLDOCHANDLE OUTPUT, @OBJECTKEYXML
IF @EXECRESULT &lt;&gt; 0
BEGIN
SELECT @ERROR_MESSAGE = message FROM APM.messages WHERE id = 50002
RAISERROR(@ERROR_MESSAGE, 16, 1, 'EventDetail_sync', @EXECRESULT)
END

DECLARE @EVENTDETAIL TABLE (
eventrowguid nvarchar(15) collate database_default
,name nvarchar(50) collate database_default
,val1 nvarchar(255) collate database_default
,val2 nvarchar(255) collate database_default
,client bit
)

INSERT @EVENTDETAIL (
eventrowguid
,name
,val1
,val2
,client
)
SELECT
eventrowguid
,name
,val1
,val2
,client
FROM OPENXML(@XMLDOCHANDLE, 'rows/row', 2) WITH (
eventrowguid nvarchar(15)
,name nvarchar(50)
,val1 nvarchar(255)
,val2 nvarchar(255)
,client bit
) xml


EXEC sp_xml_removedocument @XMLDOCHANDLE

SET @XMLDOCHANDLE = NULL

-- Fill Ip table--------
INSERT APM.ip (ip, subnetc)
SELECT DISTINCT
sync.val1
,sync.val2
FROM
@EVENTDETAIL sync
WHERE
sync.name = 'IPADDRESS' AND
sync.val1 IS NOT NULL AND sync.val1 &lt;&gt; '' AND NOT EXISTS(SELECT * FROM APM.ip ip WHERE ip.ip = sync.val1)

UPDATE e
SET e.ipid = ip.ipid
FROM
APM.Event e
JOIN @EVENTDETAIL sync ON e.rowguid = sync.eventrowguid AND sync.name = 'IPADDRESS' and sync.client = 0
JOIN APM.Ip ip ON sync.val1 = ip.ip


SET @UPDATED_ROWCOUNT = @@ROWCOUNT

SELECT @CHANGEDROWCOUNT = COUNT(*) FROM @EVENTDETAIL WHERE name = 'IPADDRESS' AND client = 0

SET @ROWNOTAFFECTED = @CHANGEDROWCOUNT - @UPDATED_ROWCOUNT
END TRY
BEGIN CATCH
IF (@@TRANCOUNT &gt; 0)
ROLLBACK TRAN

SELECT
@ERRORNUMBER = ERROR_NUMBER()
,@ERRORSEVERITY = ERROR_SEVERITY()
,@ERRORSTATE = ERROR_STATE()
,@ERRORLINE = ERROR_LINE()
,@ERRORPROCEDURE = ISNULL(ERROR_PROCEDURE(), '-')
,@ERRORMESSAGETEXT = ERROR_MESSAGE()

SET @ERRORIND = 1
END CATCH

IF @XMLDOCHANDLE IS NOT NULL
EXEC sp_xml_removedocument @XMLDOCHANDLE

-- report error if any
IF (@ERRORIND = 1)
BEGIN
DECLARE @ADJUSTEDERRORSEVERITY int

SET @ADJUSTEDERRORSEVERITY = CASE
WHEN @ERRORSEVERITY = 2601 OR @ERRORSEVERITY = 2627 THEN 0
WHEN @ERRORSEVERITY &gt; 18 THEN 18
ELSE @ERRORSEVERITY
END
SELECT @ERROR_MESSAGE = message FROM APM.Messages WHERE id = 50004
RAISERROR (@ERROR_MESSAGE, @ADJUSTEDERRORSEVERITY, 1
,@ERRORNUMBER
,@ERRORSEVERITY
,@ERRORSTATE
,@ERRORPROCEDURE
,@ERRORLINE
,@ERRORMESSAGETEXT
)
END
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.GetDependentComputersList'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.GetDependentComputersList AS RETURN 1')
END
GO

ALTER PROCEDURE APM.GetDependentComputersList
@SOURCE NVARCHAR(MAX)
,@COMPUTERS NVARCHAR(MAX)
,@STARTDATE DateTime
,@ENDDATE DateTime
AS
BEGIN
CREATE TABLE #SOURCEMACHINEMULTIVALUE
(
TYPEID int, VALUE int
)
INSERT
INTO #SOURCEMACHINEMULTIVALUE
SELECT
p.typeid,
CAST(p.value AS Int)
FROM
APM.GetMultiParameters(@SOURCE, @COMPUTERS) p
--Select machine for server events
SELECT DISTINCT m.machine, m.machineid
FROM
APM.Machine AS m (NOLOCK)
JOIN #SOURCEMACHINEMULTIVALUE AS f2 ON (f2.TYPEID = 2 and f2.VALUE = M.machineid)
UNION
--Computer parameter have to contain at leat one value, or an exception occures in reports
select N'', -1
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.ApplicationStatusSummaryStatistics'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.ApplicationStatusSummaryStatistics AS RETURN 1')
END
GO

/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: ApplicationStatusSummaryStatistics */
/* USED IN: Application Status Report */
/* INPUT PARAMETERS: */
/* @SOURCEIDS - List of the source id, separated by comma. Exp: '1,2,3' */
/* @COMPUTERIDS - List of the computer id, separated by comma. Exp: '1,2,3' */
/* @ENDDATE - End date of the period */
/* @PERIOD - Period type(Day, Week or Month). */
/* - Use for the Start Date calculate of the period */
/* @AVERAGEINTERVAL- This value specifies interval, for which average values */
/* be calculated. Possible values: 1(1 month), 2(2 month), */
/* 3(3 month), 6(6 month), 17 (7 day) */
/* @TRESHOLD - Event duration treshold */
/* @PROBLEM - Event problem type (all, critical) */
/* @TIMEZONE - correlate parameter (timezone by min) */
/* - for the End Date calculate */
/************************************************************************************/
ALTER PROCEDURE APM.ApplicationStatusSummaryStatistics
@SOURCEIDS NVARCHAR(MAX),
@COMPUTERIDS NVARCHAR(MAX),
@ENDDATE DATETIME,
@PERIOD INT,
@AVERAGEINTERVAL INT,
@THRESHOLD INT,
@PROBLEM NVARCHAR(10),
@TIMEZONE INT,
@PMSTATUS NVARCHAR(50)
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON;

/************************************************************************************/
/* Prepare auxiliary variables for the further calculation */
/************************************************************************************/

--Calculate End Date in view of timezone
SET @ENDDATE = DATEADD(minute, -@TIMEZONE, @ENDDATE)

--Used for counting average value for last three months
DECLARE @PERIODDAYSCOUNT int
SET @PERIODDAYSCOUNT = APM.GetQueryDateCount(@PERIOD, @ENDDATE)

--Calculate Start Date in view of period type
DECLARE @STARTDATE DateTime
SET @STARTDATE = DATEADD(d, -@PERIODDAYSCOUNT, @ENDDATE)

--Calculate previos period Start Date
DECLARE @LASTPERIODSTARTDATE DateTime
SET @LASTPERIODSTARTDATE = DATEADD(d, -@PERIODDAYSCOUNT, @STARTDATE)

--Calculate average period Start Date
DECLARE @AVERAGEPERIODSTARTDATE DateTime
SET @AVERAGEPERIODSTARTDATE = (CASE
WHEN @AVERAGEINTERVAL &lt; 10 THEN DATEADD(month, -@AVERAGEINTERVAL, @STARTDATE)
ELSE DATEADD(day, -(@AVERAGEINTERVAL-10), @STARTDATE)
END)

DECLARE @PROCESSORCOUNTERID INT
SELECT @PROCESSORCOUNTERID = PCtypeId FROM APM.PCType (NOLOCK) WHERE type = N'\Process\% Processor Time'

DECLARE @MEMORYCOUNTERID INT
SELECT @MEMORYCOUNTERID = PCtypeId FROM APM.PCType (NOLOCK) WHERE type = N'\Process\Private Bytes'

DECLARE @IOCOUNTERID INT
SELECT @IOCOUNTERID = PCtypeId FROM APM.PCType (NOLOCK) WHERE type = N'\Process\IO Data Bytes/sec'

DECLARE @MONITOREDREQUESTCOUNTERID INT
SELECT @MONITOREDREQUESTCOUNTERID = PCtypeId FROM APM.PCType (NOLOCK) WHERE type = N'\Apps\Monitored Requests'

DECLARE @REQUESTTIMECOUNTERID INT
SELECT @REQUESTTIMECOUNTERID = PCtypeId FROM APM.PCType (NOLOCK) WHERE type = N'\Apps\Avg. Request Time'

/************************************************************************************/
/* ASSISTING TEMP TABLES */
/************************************************************************************/

-- Filter table, which contains machine ids and source ids
-- typeid defines filter type - 1 for source and 2 for machine
-- valueId filter value - source id and machine id
CREATE TABLE #SOURCEMACHINEFILTERTABLE(
TYPEID INT,
VALUEID INT
)

-- Fill table #SOURCEMACHINEFILTERTABLE
INSERT
INTO #SOURCEMACHINEFILTERTABLE
SELECT
p.typeId AS TYPEID,
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@SOURCEIDS, @COMPUTERIDS) AS p

-- Filter table, which contains PM Statuses of Events
CREATE TABLE #PMSTATUSFILTERTABLE(
VALUEID INT
)

-- Fill table #PMSTATUSFILTERTABLE
INSERT
INTO #PMSTATUSFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@PMSTATUS, N'') AS p

/************************************************************************************/
/* Filtered events for further manipulations */
/************************************************************************************/
;WITH GetSummaryStatistics_EventsFiltered AS
(
SELECT
e.SourceId,
e.EventId,
e.UtcEventDate AS Date,
ABS(DATEDIFF(d, DATEADD(minute, @TIMEZONE, e.UtcEventDate), @ENDDATE)) / @PERIODDAYSCOUNT AS PeriodId
FROM
APM.Event AS e
JOIN #SOURCEMACHINEFILTERTABLE AS f1 ON (f1.TYPEID = 1 AND f1.VALUEID = e.SourceId)
JOIN #SOURCEMACHINEFILTERTABLE AS f2 ON (f2.TYPEID = 2 AND f2.VALUEID = e.MachineId)
JOIN #PMSTATUSFILTERTABLE AS f3 ON (f3.VALUEID = e.PMStatus)
WHERE
(e.EventClassType = N'exception' OR (e.EventClassType = 'performance' AND e.eventduration / 1000000.0 &gt;= @THRESHOLD))
AND (e.category LIKE @PROBLEM OR e.category IS NULL)
AND e.utceventdate &gt;= @AVERAGEPERIODSTARTDATE
AND e.utceventdate &lt; @ENDDATE
AND (e.HeavyLight &lt;&gt; 0 OR e.HeavyLight IS NULL)

),

/************************************************************************************/
/* Resource Utilizayion Queries */
/************************************************************************************/
-- Calculate resource utilization by Source in one hour.
-- Aggregation between instances should be done here (for cases when one source run in several process in one hour)
SourceHourlyResourceUtilization AS
(
SELECT
ph.MachineId,
ph.SourceId,
ph.UTCDate,
ph.PCTypeId AS [Type],

---------- Pivot instance count by period type -----------
(CASE
WHEN ph.UtcDate &gt;= @LASTPERIODSTARTDATE AND ph.UtcDate &lt; @STARTDATE
THEN SUM(ph.SampleCount)*1.0/MAX(ph.PackageCounter)
END) AS LastInstanceCount,
(CASE
WHEN ph.UtcDate &gt;= @STARTDATE AND ph.UtcDate &lt; @ENDDATE
THEN SUM(ph.SampleCount)*1.0/MAX(ph.PackageCounter)
END) AS CurInstanceCount,
(CASE
WHEN ph.utcdate &gt;= @AVERAGEPERIODSTARTDATE AND ph.utcdate &lt; @STARTDATE
THEN SUM(ph.SampleCount)*1.0/MAX(ph.PackageCounter)
END) AS AvgInstanceCount,

---------- Pivot resource value by period type -----------
(CASE
WHEN ph.UtcDate &gt;= @LASTPERIODSTARTDATE AND ph.UtcDate &lt; @STARTDATE THEN SUM(SumValue)/SUM(SampleCount)
END) AS LastValue,
(CASE
WHEN ph.UtcDate &gt;= @STARTDATE AND ph.UtcDate &lt; @ENDDATE THEN SUM(SumValue)/SUM(SampleCount)
END) AS CurValue,
(CASE
WHEN ph.utcdate &gt;= @AVERAGEPERIODSTARTDATE AND ph.utcdate &lt; @STARTDATE THEN SUM(SumValue)/SUM(SampleCount)
END) AS AvgValue,

ABS(DATEDIFF(day, DATEADD(minute, @TIMEZONE, ph.utcdate), @ENDDATE)) / @PERIODDAYSCOUNT AS PeriodId
FROM
APM.PerfHourly AS ph (NOLOCK)
--Join with #SOURCEMACHINEFILTERTABLE with typeId = 1 provides filtering perfHourly by sourceid
JOIN #SOURCEMACHINEFILTERTABLE AS f1 ON (f1.TYPEID = 1 AND f1.VALUEID = ph.SourceId)
--Join with #SOURCEMACHINEFILTERTABLE with typeId = 2 provides filtering perfHourly by machineid
JOIN #SOURCEMACHINEFILTERTABLE AS f2 ON (f2.TYPEID = 2 AND f2.VALUEID = ph.MachineId)
WHERE
ph.UTCDate &gt;= @AVERAGEPERIODSTARTDATE
AND ph.UTCDate &lt; @ENDDATE
AND ph.PCTypeId IN (@PROCESSORCOUNTERID, @IOCOUNTERID, @MEMORYCOUNTERID)
GROUP BY
ph.MachineId,
ph.SourceId,
ph.UTCDate,
ph.PCTypeId
),
--Calculate average application resource utilization over all specified period per machine
--and for specified grouping period
ApplicationResourceUtilizationByMachines AS
(
SELECT
ph.MachineId,
ph.SourceId,
ph.PeriodId,
-- Instance count should be same for different resource types in one hour for one process
-- and averaging them won't make any difference but allow to avoid one aggregation step
AVG(ph.CurInstanceCount) AS CurInstanceCount,
AVG(ph.LastInstanceCount) AS LastInstanceCount,
AVG(ph.AvgInstanceCount) AS AvgInstanceCount,

---------- Pivot resource by counter type -----------

----------- 'Process% Processor Time' counter -------------------
AVG(CASE WHEN ph.type = @PROCESSORCOUNTERID THEN ph.CurValue END) AS CurCPUSum,
AVG(CASE WHEN ph.type = @PROCESSORCOUNTERID THEN ph.LastValue END) AS LastCPUSum,
AVG(CASE WHEN ph.type = @PROCESSORCOUNTERID THEN ph.AvgValue END) AS AvgCPUSum,

----------- 'ProcessPrivate Bytes' counter -------------------
AVG(CASE WHEN ph.type = @MEMORYCOUNTERID THEN ph.CurValue END) AS CurMemSum,
AVG(CASE WHEN ph.type = @MEMORYCOUNTERID THEN ph.LastValue END) AS LastMemSum,
AVG(CASE WHEN ph.type = @MEMORYCOUNTERID THEN ph.AvgValue END) AS AvgMemSum,

----------- 'ProcessIO Data Bytes/sec' counter -------------------
AVG(CASE WHEN ph.type = @IOCOUNTERID THEN ph.CurValue END) AS CurIOSum,
AVG(CASE WHEN ph.type = @IOCOUNTERID THEN ph.LastValue END) AS LastIOSum,
AVG(CASE WHEN ph.type = @IOCOUNTERID THEN ph.AvgValue END) AS AvgIOSum
FROM
SourceHourlyResourceUtilization AS ph
GROUP BY
ph.MachineId,
ph.SourceId,
ph.PeriodId
),
-- Count Monitored Requests and Avg. Request Timefor Application on each machine
-- as source can run on different machines with same process name and app pool, but different sources set,
-- it is important to group by machine to, to avoid calculation of requests from the other app pool
-- Summarize request count in each period (PeriodId differs only for AvgValue)
ApplicationNetAppCountersByMachinePrepare AS
(
SELECT
ph.MachineId,
ph.SourceId,
----------------- Pivot Monitor Request Counter by period ------------------
CASE WHEN ph.UtcDate &gt;= @LASTPERIODSTARTDATE AND ph.UtcDate &lt; @STARTDATE
THEN SUM(CASE WHEN ph.PCTypeID = @MONITOREDREQUESTCOUNTERID THEN ph.SumValue END)
END AS LastMonRequest,
CASE WHEN ph.UtcDate &gt;= @STARTDATE AND ph.UtcDate &lt; @ENDDATE
THEN SUM(CASE WHEN ph.PCTypeID = @MONITOREDREQUESTCOUNTERID THEN ph.SumValue END)
END AS CurMonRequest,
CASE WHEN ph.utcdate &gt;= @AVERAGEPERIODSTARTDATE AND ph.utcdate &lt; @STARTDATE
THEN SUM(CASE WHEN ph.PCTypeID = @MONITOREDREQUESTCOUNTERID THEN ph.SumValue END)
END AS AvgMonRequest,

----------------- Pivot Avg. Request Time Counter by period ------------------
CASE WHEN ph.UtcDate &gt;= @LASTPERIODSTARTDATE AND ph.UtcDate &lt; @STARTDATE
THEN AVG(CASE WHEN ph.PCTypeID = @REQUESTTIMECOUNTERID THEN ph.SumValue / ph.SampleCount END)
END AS LastAvgReqTime,
CASE WHEN ph.UtcDate &gt;= @STARTDATE AND ph.UtcDate &lt; @ENDDATE
THEN AVG(CASE WHEN ph.PCTypeID = @REQUESTTIMECOUNTERID THEN ph.SumValue / ph.SampleCount END)
END AS CurAvgReqTime,
CASE WHEN ph.utcdate &gt;= @AVERAGEPERIODSTARTDATE AND ph.utcdate &lt; @STARTDATE
THEN AVG(CASE WHEN ph.PCTypeID = @REQUESTTIMECOUNTERID THEN ph.SumValue / ph.SampleCount END)
END AS AvgReqTime,

ABS(DATEDIFF(day, DATEADD(minute, @TIMEZONE, ph.utcdate), @ENDDATE)) / @PERIODDAYSCOUNT AS PeriodId
FROM
APM.PerfHourly AS ph (NOLOCK)
--Join with #SOURCEMACHINEFILTERTABLE provides filtering perfHourly by sourceid
JOIN #SOURCEMACHINEFILTERTABLE AS f1 ON (f1.TYPEID = 1 AND ph.SourceId = f1.VALUEID)
--Join with #SOURCEMACHINEFILTERTABLE provides filtering perfHourly by machineid
JOIN #SOURCEMACHINEFILTERTABLE AS f2 ON (f2.TYPEID = 2 AND f2.VALUEID = ph.MachineId)
WHERE
ph.UTCDate &gt;= @AVERAGEPERIODSTARTDATE
AND ph.UTCDate &lt; @ENDDATE
AND ph.PCTypeID IN (@REQUESTTIMECOUNTERID, @MONITOREDREQUESTCOUNTERID)
GROUP BY
ph.MachineId,
ph.SourceId,
ph.UTCDate
),
--Calculate average request time and sum request count for specified grouping period
ApplicationNetAppCountersByMachine AS
(
SELECT
ph.MachineId,
ph.SourceId,
ph.PeriodId,
SUM(ph.LastMonRequest) AS LastMonRequest,
SUM(ph.CurMonRequest) AS CurMonRequest,
SUM(ph.AvgMonRequest) AS AvgMonRequest,
AVG(ph.LastAvgReqTime) AS LastAvgReqTime,
AVG(ph.CurAvgReqTime) AS CurAvgReqTime,
AVG(ph.AvgReqTime) AS AvgReqTime
FROM
ApplicationNetAppCountersByMachinePrepare ph
GROUP BY
ph.MachineId,
ph.SourceId,
ph.PeriodId
),
--Union .NET counters and process counters for period Id.
--PeriodId differs only for average, so for current and last period it doesn't matter which agg function is taken
ActivePreparePCounters AS (
SELECT
pc.machineId,
pc.SourceId,

MAX(netApp.CurMonRequest) AS CurReqCount,
MAX(netApp.LastMonRequest) AS LastReqCount,
AVG(netApp.AvgMonRequest) AS AvgReqCount,

MAX(netApp.CurAvgReqTime) AS CurAvgReqTime,
MAX(netApp.LastAvgReqTime) AS LastAvgReqTime,
AVG(netApp.AvgReqTime) AS AvgReqTime,

MAX(pc.CurInstanceCount) AS CurInstanceCount,
MAX(pc.LastInstanceCount) AS LastInstanceCount,
AVG(pc.AvgInstanceCount) AS AvgInstanceCount,

MAX(pc.CurCPUSum) AS CurCPUSum,
MAX(pc.LastCPUSum) AS LastCPUSum,
AVG(pc.AvgCPUSum) AS AvgCPUSum,

MAX(pc.CurMemSum) AS CurMemSum,
MAX(pc.LastMemSum) AS LastMemSum,
AVG(pc.AvgMemSum) AS AvgMemSum,

MAX(pc.CurIOSum) AS CurIOSum,
MAX(pc.LastIOSum) AS LastIOSum,
AVG(pc.AvgIOSum) AS AvgIOSum
FROM
ApplicationResourceUtilizationByMachines AS pc
LEFT JOIN ApplicationNetAppCountersByMachine AS netApp ON netApp.MachineId = pc.MachineId
AND netApp.SourceId = pc.SourceId AND netApp.PeriodId = netApp.PeriodId
GROUP BY
pc.machineId,
pc.SourceId
),
--Group PC between machines
PCounters AS
(
SELECT
pc.SourceId AS SourceId,
SUM(pc.CurReqCount) AS CurReqCount,
SUM(pc.LastReqCount) AS LastReqCount,
SUM(pc.AvgReqCount) AS AvgReqCount,
AVG(pc.CurAvgReqTime) AS CurAvgReqTime,
AVG(pc.LastAvgReqTime) AS LastAvgReqTime,
AVG(pc.AvgReqTime) AS AvgReqTime,
AVG(pc.CurCPUSum / COALESCE(m.CPUCount, 1)) AS CurCPUSum,
AVG(pc.LastCPUSum / COALESCE(m.CPUCount, 1)) AS LastCPUSum,
AVG(pc.AvgCPUSum / COALESCE(m.CPUCount, 1)) AS AvgCPUSum,
AVG(pc.CurMemSum) AS CurMemSum,
AVG(pc.LastMemSum) AS LastMemSum,
AVG(pc.AvgMemSum) AS AvgMemSum,
AVG(pc.CurIOSum) AS CurIOSum,
AVG(pc.LastIOSum) AS LastIOSum,
AVG(pc.AvgIOSum) AS AvgIOSum,
AVG(pc.CurInstanceCount) AS CurInstanceCount,
AVG(pc.LastInstanceCount) AS LastInstanceCount,
AVG(pc.AvgInstanceCount) AS AvgInstanceCount
FROM
ActivePreparePCounters AS pc
JOIN APM.Machine AS m ON m.MachineId = pc.MachineId
GROUP BY
pc.SourceId
),
PrepareEvents AS
(
SELECT
e.SourceId,
e.PeriodId,
COUNT(CASE WHEN e.date &gt;= @STARTDATE AND e.date &lt; @ENDDATE THEN e.eventid END) AS CurEventCount,
COUNT(CASE WHEN e.date &gt;= @LASTPERIODSTARTDATE AND e.date &lt; @STARTDATE THEN e.eventid END) AS LastEventCount,
COUNT(CASE WHEN e.date &lt; @STARTDATE THEN e.eventid END) AS AverageEventCount
FROM
GetSummaryStatistics_EventsFiltered AS e
GROUP BY
e.SourceId,
e.PeriodId
),
--Aggregate average event count. As PeriodId differs only for avg value, it doesn't matter which aggregation function is taken for other values
Events AS
(
SELECT
e.SourceId,
MAX(e.CurEventCount) AS CurEventCount,
MAX(e.LastEventCount) AS LastEventCount,
--Average counting should not include current period
AVG(CASE WHEN PeriodID &gt; 0 THEN e.AverageEventCount END) AS AverageEventCount
FROM
PrepareEvents AS e
GROUP BY
e.SourceId
),
-- this query separated from GetSummaryStatistics_EventsFiltered as it has smaller period
GetSummaryStatistics_EventsProblemsFiltered AS
(
SELECT
e.SourceId,
e.EventId,
e.EventClassType,
e.Description,
e.RootNodeName,
--Forms description for perfNode this way to avoid duration in event description
COALESCE(RIGHT(pn.Description, LEN(pn.Description) - CHARINDEX(':', pn.Description)), N'') AS PerfNode,
e.UtcEventDate AS Date,
eg.FirstEventDate
FROM
APM.Event AS e
JOIN APM.EventGroup AS eg ON e.eventgroupId = eg.EventGroupId
JOIN #SOURCEMACHINEFILTERTABLE AS f1 ON (f1.TYPEID = 1 AND f1.VALUEID = e.SourceId)
JOIN #SOURCEMACHINEFILTERTABLE AS f2 ON (f2.TYPEID = 2 AND f2.VALUEID = e.MachineId)
JOIN #PMSTATUSFILTERTABLE AS f3 ON (f3.VALUEID = e.PMStatus)
OUTER APPLY (
SELECT TOP(1)
pn.description
FROM
APM.PerformanceNode AS pn
WHERE
pn.eventid = e.eventid AND e.resourceid = pn.resourceid
ORDER BY
pn.selfduration DESC
) AS pn
WHERE
(e.EventClassType = N'exception' OR (e.EventClassType = 'performance' AND e.eventduration / 1000000.0 &gt;= @THRESHOLD))
AND (e.category LIKE @PROBLEM OR e.category IS NULL)
AND e.utceventdate &gt;= @LASTPERIODSTARTDATE
AND e.utceventdate &lt; @ENDDATE
AND (e.HeavyLight &lt;&gt; 0 OR e.HeavyLight IS NULL)

),
EventProblems AS
(
SELECT
e.SourceId,
COUNT(DISTINCT CASE WHEN (EventClassType = 'Performance' AND e.date &gt;= @STARTDATE AND e.date &lt; @ENDDATE) THEN rootnodeName + perfNode END) AS CurPerformanceProblemCount,
COUNT(DISTINCT CASE WHEN (EventClassType &lt;&gt; 'Performance' AND e.date &gt;= @STARTDATE AND e.date &lt; @ENDDATE) THEN e.description END) AS CurExceptionProblemCount,
COUNT(CASE WHEN (EventClassType = 'Performance' AND e.date &gt;= @STARTDATE AND e.date &lt; @ENDDATE) THEN e.eventid END) AS CurPerformanceEventCount,
COUNT(CASE WHEN (EventClassType &lt;&gt; 'Performance' AND e.date &gt;= @STARTDATE AND e.date &lt; @ENDDATE) THEN e.eventid END) AS CurExceptionEventCount,
COUNT(DISTINCT CASE WHEN (EventClassType = 'Performance' AND e.date &gt;= @LASTPERIODSTARTDATE AND e.date &lt; @STARTDATE) THEN rootnodeName + perfNode END) AS LastPerformanceProblemCount,
COUNT(DISTINCT CASE WHEN (EventClassType &lt;&gt; 'Performance' AND e.date &gt;= @LASTPERIODSTARTDATE AND e.date &lt; @STARTDATE) THEN e.description END) AS LastExceptionProblemCount,
COUNT(CASE WHEN (EventClassType = 'Performance' AND e.date &gt;= @LASTPERIODSTARTDATE AND e.date &lt; @STARTDATE) THEN e.eventid END) AS LastPerformanceEventCount,
COUNT(CASE WHEN (EventClassType &lt;&gt; 'Performance' AND e.date &gt;= @LASTPERIODSTARTDATE AND e.date &lt; @STARTDATE) THEN e.eventid END) AS LastExceptionEventCount,
COUNT(DISTINCT CASE WHEN (e.EventClassType = 'performance' AND e.firsteventdate &gt;= @STARTDATE) THEN e.rootnodeName + perfNode END) as NewPerfProblemsCount,
COUNT(DISTINCT CASE WHEN (e.EventClassType &lt;&gt; 'performance' AND e.firsteventdate &gt;= @STARTDATE) THEN e.description END) as NewExpProblemsCount
FROM
GetSummaryStatistics_EventsProblemsFiltered AS e
GROUP BY
e.SourceId
),
ResultQuery AS
(
SELECT
ROW_NUMBER() OVER(ORDER BY s.SourceId) AS Id,
s.SourceId,
s.Source,
COALESCE(pc.CurReqCount, 0) AS CurMonitoredRequestSum,
COALESCE(pc.LastReqCount, 0) AS LastMonitoredRequestSum,
COALESCE(pc.AvgReqCount, 0) AS AvgMonitoredRequestSum,
COALESCE(pc.CurAvgReqTime, 0) AS CurAvrValue,
COALESCE(pc.LastAvgReqTime, 0) AS LastAvgValue,
COALESCE(pc.AvgReqTime, 0) AS AvgValue,
COALESCE(pc.CurCPUSum, 0) AS CurCPUValue,
COALESCE(pc.LastCPUSum, 0) AS LastCPUValue,
COALESCE(pc.AvgCPUSum, 0) AS CPUAvgValue,
COALESCE(pc.CurMemSum, 0) AS CurMemValue,
COALESCE(pc.LastMemSum, 0) AS LastMemValue,
COALESCE(pc.AvgMemSum, 0) AS MemAvgValue,
COALESCE(pc.CurIOSum, 0) AS CurIOValue,
COALESCE(pc.LastIOSum, 0) AS LastIOValue,
COALESCE(pc.AvgIOSum, 0) AS IOAvgValue,

COALESCE(pc.CurInstanceCount, 0) AS CurInstanceCount,
COALESCE(pc.LastInstanceCount, 0) AS LastInstanceCount,
COALESCE(pc.AvgInstanceCount, 0) AS AvgInstanceCount,

COALESCE(E.LastEventCount, 0) AS LastEventCount,
COALESCE(e.CurEventCount, 0) AS CurrentEventCount,
COALESCE(e.AverageEventCount, 0) AS AvgEventsCount,

COALESCE(p.CurExceptionEventCount, 0) AS CurExceptionEventCount,
COALESCE(p.CurPerformanceEventCount, 0) AS CurPerformanceEventCount,
COALESCE(p.LastPerformanceEventCount, 0) AS LastPerformanceEventCount,
COALESCE(p.LastExceptionEventCount, 0) AS LastExceptionEventCount,
COALESCE(p.CurPerformanceProblemCount, 0) AS CurPerformanceProblemCount,
COALESCE(p.CurExceptionProblemCount, 0) AS CurExceptionProblemCount,
COALESCE(p.LastPerformanceProblemCount, 0) AS LastPerformanceProblemCount,
COALESCE(p.LastExceptionProblemCount, 0) AS LastExceptionProblemCount,
COALESCE(p.NewPerfProblemsCount, 0) AS NewPerfProblemsCount,
COALESCE(p.NewExpProblemsCount, 0) AS NewExpProblemsCount
FROM
#SOURCEMACHINEFILTERTABLE AS sd
JOIN APM.Source AS s (NOLOCK) ON sd.VALUEID = s.SourceId
LEFT OUTER JOIN PCounters AS pc ON s.SourceId = pc.Sourceid
LEFT OUTER JOIN Events AS e ON s.Sourceid = e.Sourceid
LEFT OUTER JOIN EventProblems AS p ON s.Sourceid = p.Sourceid
WHERE
sd.TYPEID = 1
)
SELECT
LastResults.Id AS RowId,
SourceId,
Source,
-------Instance Count----------
CurInstanceCount,
LastInstanceCount,
AvgInstanceCount,
-------MonitoredRequest--------
CurMonitoredRequestSum,
LastMonitoredRequestSum,
AvgMonitoredRequestSum,
-------Avg value----------
CurAvrValue,
LastAvgValue,
AvgValue,
------CPU Value----------
CurCPUValue,
LastCPUValue,
CPUAvgValue,
------ Mem value------------
CurMemValue,
LastMemValue,
MemAvgValue,
--------- IO value-------------
CurIOValue,
LastIOValue,
IOAvgValue,
------- Events count----------
AvgEventsCount,
CurrentEventCount,
LastEventCount,
--------- Exception &amp; Performance Event Count ---------
CurExceptionEventCount,
CurPerformanceEventCount,
LastPerformanceEventCount,
LastExceptionEventCount,
-------- Exception &amp; Performance Problem Count ---------
CurPerformanceProblemCount,
CurExceptionProblemCount,
LastPerformanceProblemCount,
LastExceptionProblemCount,
NewPerfProblemsCount,
NewExpProblemsCount
FROM
ResultQuery AS LastResults
ORDER BY
RowId
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.ApplicationStatusDrillthrough'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.ApplicationStatusDrillthrough AS RETURN 1')
END
GO

/****************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: ApplicationStatusDrillthrough */
/* USED IN: Application Status Report, Application Daily Activity */
/* INPUT PARAMETERS: */
/* @SOURCEIDS - List of the source id, separated by comma. Exp: '1,2,3' */
/* @COMPUTERIDS - List of the computer id, separated by comma. Exp: '1,2,3' */
/* @ENDDATE - End date of the period */
/* @PERIOD - Period type(Day, Week or Month). */
/* - Use for the Start Date calculate of the period */
/* @AVERAGEINTERVAL- This value specifies interval, for which average values will */
/* be calculated. Possible values: 1(1 month), 2(2 month), */
/* 3(3 month), 6(6 month), 17 (7 day) */
/* @GROUPBY - Specifies result gouping type. Possible values: */
/* Hour - Group by hours. Rersult set will contain 24 rows */
/* corresponding to 24 hours. Date field - 0-23, Hour field - 0 */
/* WeekDay - Group by week days. For this grouping type extra grouping */
/* is applied - by hours. So result data set contains 7*24 rows. */
/* Date field values - 1-7, Hour fields - 0-23 */
/* Month - Group by Month. For this grouping type extra grouping */
/* is applied - by months. So result data set contains 12*24 rows. */
/* and Hour field - 0-23 */
/* @TRESHOLD - Event duration treshold */
/* @PROBLEM - Event problem type (all, critical) */
/* @TIMEZONE - correlate parameter (timezone by min) */
/* - for the End Date calculate */
/****************************************************************************************/
alter PROCEDURE APM.ApplicationStatusDrillthrough
@SOURCEIDS NVARCHAR(MAX),
@COMPUTERIDS NVARCHAR(MAX),
@ENDDATE DATETIME,
@TIMEZONE INT,
@PERIOD INT,
@AVERAGEINTERVAL INT,
@GROUPBY NVARCHAR(10),
@THRESHOLD INT,
@PROBLEM NVARCHAR(10),
@PMSTATUS NVARCHAR(50)
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON;

/************************************************************************************/
/* Prepare auxiliary variables for the further calculation */
/************************************************************************************/

SET @ENDDATE = DATEADD(minute, -@TIMEZONE, @ENDDATE)

DECLARE @STARTDATE DateTime
SET @STARTDATE = DATEADD(d, -(CASE WHEN @PERIOD = 1 THEN 1 WHEN @PERIOD = 2 THEN 7 ELSE 31 END), @ENDDATE)

DECLARE @LASTPERIODSTARTDATE DateTime
SET @LASTPERIODSTARTDATE = DATEADD(d, -APM.GetQueryDateCount(@PERIOD, @STARTDATE), @STARTDATE)

DECLARE @AVERAGEPERIODSTARTDATE DateTime
SET @AVERAGEPERIODSTARTDATE = (CASE
WHEN @AVERAGEINTERVAL &lt; 10 THEN DATEADD(month, -@AVERAGEINTERVAL, @STARTDATE)
ELSE DATEADD(day, -(@AVERAGEINTERVAL-10), @STARTDATE)
END)

--Used for counting average value for last three months
DECLARE @PERIODDAYSCOUNT int
SET @PERIODDAYSCOUNT = APM.GetQueryDateCount(@PERIOD, @STARTDATE);

DECLARE @PROCESSORCOUNTERID INT
SELECT @PROCESSORCOUNTERID = PCtypeId FROM apm.PCType (NOLOCK) WHERE TYPE = N'\Process\% Processor Time'

DECLARE @MEMORYCOUNTERID INT
SELECT @MEMORYCOUNTERID = PCtypeId FROM apm.PCType (NOLOCK) WHERE TYPE = N'\Process\Private Bytes'

DECLARE @IOCOUNTERID INT
SELECT @IOCOUNTERID = PCtypeId FROM apm.PCType (NOLOCK) WHERE TYPE = N'\Process\IO Data Bytes/sec'

DECLARE @MONITOREDREQUESTCOUNTERID INT
SELECT @MONITOREDREQUESTCOUNTERID = PCtypeId FROM apm.PCType (NOLOCK) WHERE TYPE = N'\Apps\Monitored Requests'

DECLARE @REQUESTTIMECOUNTERID INT
SELECT @REQUESTTIMECOUNTERID = PCtypeId FROM apm.PCType (NOLOCK) WHERE TYPE = N'\Apps\Avg. Request Time'
/************************************************************************************/
/* ASSISTING TEMP TABLES */
/************************************************************************************/
-- Filter table, which contains machine ids and source ids
-- typeid defines filter type - 1 for source and 2 for machine
-- valueId filter value - source id and machine id
CREATE TABLE #SOURCEMACHINEFILTERTABLE(
TYPEID INT,
VALUEID INT
)

-- Fill table #SOURCEMACHINEFILTERTABLE
INSERT
INTO #SOURCEMACHINEFILTERTABLE
SELECT
p.typeId AS TYPEID,
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@SOURCEIDS, @COMPUTERIDS) AS p

-- Filter table, which contains PM Statuses of Events
CREATE TABLE #PMSTATUSFILTERTABLE(
VALUEID INT
)

-- Fill table #PMSTATUSFILTERTABLE
INSERT
INTO #PMSTATUSFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@PMSTATUS, N'') AS p

-- To form application pool with all sources run in it, it is need to get all sources and its process
CREATE TABLE #PROCESSFORSOURCE
(
SOURCEID INT,
PCPROCESSID INT,
MACHINEID INT,
EXTRAINFO NVARCHAR(255) collate database_default,
PROCESS NVARCHAR(255) collate database_default
)

INSERT INTO #PROCESSFORSOURCE
SELECT
ph.SOURCEID,
ph.PCPROCESSID,
ph.MACHINEID,
COALESCE(p.EXTRAINFO, N'') AS EXTRAINFO,
--Select process name till # symbol (w3wp#1 -&gt; w3wp, w3wp -&gt; w3wp)
APM.RemoveProcessIdFromName(p.PROCESS) AS Process
FROM
(
SELECT DISTINCT
ph.SOURCEID,
ph.PCPROCESSID,
ph.MACHINEID
FROM
APM.PerfHourly AS ph (NOLOCK)
WHERE
ph.PCPROCESSID IS NOT NULL
AND ph.UTCDATE &gt;= @STARTDATE
AND ph.UTCDATE &lt; @ENDDATE
) AS ph
JOIN APM.PCProcess AS p (NOLOCK) ON p.PCPROCESSID = ph.PCPROCESSID
JOIN #SOURCEMACHINEFILTERTABLE AS f ON (f.TYPEID = 2 AND ph.MACHINEID = f.VALUEID)



/************************************************************************************/
/* Main query */
/************************************************************************************/

-- Report frame. It contains all sources, for which data sould be selected,
-- and date values accordingly to specified period and grouping type.
;WITH SourcesDates AS
(
SELECT
VALUEID AS sourceid,
s.SOURCE AS source,
Hours.n-1 AS hours,
D.date AS date
FROM
#SOURCEMACHINEFILTERTABLE AS source
JOIN APM.source (NOLOCK) AS s ON s.SOURCEID = source.VALUEID,
APM.fn_nums(
(CASE
WHEN @GROUPBY = 'WeekDay' THEN 24
ELSE 1
END)) AS Hours,
(SELECT
(CASE
WHEN @GROUPBY = 'Hour' THEN n-1
WHEN @GROUPBY = 'WeekDay' THEN n
WHEN @GROUPBY = 'MonthDay' THEN n
END) AS date
FROM
APM.fn_nums(
CASE
WHEN @GROUPBY = 'Hour' THEN 24
WHEN @GROUPBY = 'WeekDay' THEN 7
WHEN @GROUPBY = 'MonthDay' THEN 31
END
)
) AS D
WHERE
source.TYPEID = 1
),
-- Get sources name, ids list separated by comma per app pool
-- This info should be selected for all sources, even they are in the same application pool
-- as in this report grouping by source is applied not by application pool.
AppPoolInfo AS
(
SELECT
c.SOURCEID,
c.EXTRAINFO,
c.PROCESS,
-- all source names which have the same process name as passed in @SOURCEIDS
(SELECT A.source AS [data()]
FROM
(
SELECT DISTINCT
N'''' + s.source + N'''' + N',' AS source
FROM
#PROCESSFORSOURCE AS c1
JOIN APM.Source AS s ON c1.SOURCEID = s.SourceId
WHERE
c1.EXTRAINFO = c.EXTRAINFO
AND c1.PROCESS = c.PROCESS
AND c1.MACHINEID = c.MACHINEID
) AS A
FOR XML PATH ('')
) AS AppPoolSources
FROM
#PROCESSFORSOURCE AS c
JOIN #SOURCEMACHINEFILTERTABLE AS f ON (f.TYPEID = 1 AND f.VALUEID = c.SOURCEID)
GROUP BY
c.SOURCEID,
c.MACHINEID,
c.EXTRAINFO,
c.PROCESS
),
--Add Pool name in-front of source list, if it is executable application, then app pool countains source name
PrepareAppPoolInfo AS (
SELECT DISTINCT
CASE
WHEN COALESCE(info.EXTRAINFO,'') = '' THEN CASE info.AppPoolSources WHEN '' THEN '' ELSE LEFT(info.AppPoolSources, LEN(info.AppPoolSources)-1) END
ELSE info.EXTRAINFO + CASE info.AppPoolSources WHEN '' THEN '' ELSE ' (' + LEFT(info.AppPoolSources, LEN(info.AppPoolSources) - 1) + ')' END
END AppPool,
info.SOURCEID,
info.EXTRAINFO
FROM
AppPoolInfo AS info
),
-- Forms application pool list for each source
-- Format: AppPool1 ('Source1', 'Source2', Source3), AppPool2 ('Source1', 'Source4')
SourceAppPools AS (
SELECT
s.SOURCEID,
s.SOURCE,
COALESCE((SELECT a.AppPool AS [data()]
FROM
(
SELECT DISTINCT
info.AppPool + N',' AS AppPool
FROM
PrepareAppPoolInfo as info
WHERE
info.Sourceid = s.Sourceid
) AS A
FOR XML PATH ('')
),s.SOURCE + '-') AS AppPoolInfo
FROM
APM.Source AS s
JOIN #SOURCEMACHINEFILTERTABLE AS f ON (f.TYPEID = 1 AND f.VALUEID = s.SOURCEID)
),
--Prepares and filters events for further manipulations
ActivityBreakdown_EventsFiltered AS
(
SELECT
e.SOURCEID,
e.EVENTID,
e.UTCEVENTDATE AS eventdate,
--Removing APM.GetDatePart replacing the execution by the code below.
--It boosts the overall performance as it reduces the number of calls of scalar function
CASE @GROUPBY
WHEN 'Hour' THEN Datepart(hh, DATEADD(mi, CAST(@TIMEZONE AS int), e.utceventdate))
WHEN 'WeekDay' THEN Datepart(dw, DATEADD(mi, CAST(@TIMEZONE AS int), e.utceventdate))
WHEN 'MonthDay' THEN Datepart(d, DATEADD(mi, CAST(@TIMEZONE AS int), e.utceventdate))
END as date,
CASE
WHEN @GROUPBY = 'WeekDay'
THEN DatePart(Hour, DATEADD(mi, CAST(@TIMEZONE AS int), e.utceventdate))
ELSE 0
END AS Hour,
--hour is taken as DateDifference in day between 05/04/2009 9:00AM and 05/03/2009 9:00PM is one day,
--despite in case of @PERIOD = 'Day' it can be interpretated as one day (if 05/04/2009 9:00AM is end date), so difference should be taken as 0
ABS(DATEDIFF(hour, e.UTCEVENTDATE, @STARTDATE)) / (@PERIODDAYSCOUNT*24) AS PeriodId,
e.EVENTGROUPID,
db.ADDRESS AS SeViewerAddress
FROM
APM.Event AS e
JOIN APM.SeViewerDB AS db ON e.SEVIEWERDBID = db.SEVIEWERDBID
JOIN #SOURCEMACHINEFILTERTABLE AS f1 ON (f1.VALUEID = e.SOURCEID and f1.TYPEID = 1)
JOIN #SOURCEMACHINEFILTERTABLE AS f2 ON (f2.VALUEID = e.MACHINEID and f2.TYPEID = 2)
JOIN #PMSTATUSFILTERTABLE AS f3 ON (f3.VALUEID = e.PMSTATUS)
WHERE
((e.EVENTCLASSTYPE = N'Performance' AND e.EVENTDURATION / 1000000.0 &gt;= @THRESHOLD)
OR e.EVENTCLASSTYPE = N'exception')
AND (e.CATEGORY LIKE @PROBLEM OR e.CATEGORY IS NULL)
AND e.UTCEVENTDATE &gt;= @AVERAGEPERIODSTARTDATE
AND e.UTCEVENTDATE &lt; @ENDDATE
AND (e.HEAVYLIGHT &lt;&gt; 0 OR e.HeavyLight IS NULL)

),
/************************************************************************************/
/* Base pcounter queries */
/************************************************************************************/
-- Calculate resource utilization by Source in one hour.
-- Aggregation between instances should be done here (for cases when one source run in several process in one hour)
SourceHourlyResourceUtilization AS
(
SELECT
ph.MACHINEID,
ph.SOURCEID,
ph.UTCDATE,
ph.PCTYPEID AS Type,

---------- Pivot instance count by period type -----------
(CASE
WHEN ph.UTCDATE &gt;= @LASTPERIODSTARTDATE AND ph.UTCDATE &lt; @STARTDATE
THEN SUM(ph.SAMPLECOUNT)*1.0/MAX(ph.PACKAGECOUNTER)
END) AS LastInstanceCount,
(CASE
WHEN ph.UTCDATE &gt;= @STARTDATE AND ph.UTCDATE &lt; @ENDDATE
THEN SUM(ph.SAMPLECOUNT)*1.0/MAX(ph.PACKAGECOUNTER)
END) AS CurInstanceCount,
(CASE
WHEN ph.UTCDATE &gt;= @AVERAGEPERIODSTARTDATE AND ph.UTCDATE &lt; @STARTDATE
THEN SUM(ph.SAMPLECOUNT)*1.0/MAX(ph.PACKAGECOUNTER)
END) AS AvgInstanceCount,

---------- Pivot resource value by period type -----------
(CASE
WHEN ph.UTCDATE &gt;= @LASTPERIODSTARTDATE AND ph.UTCDATE &lt; @STARTDATE THEN SUM(SumValue)/SUM(SampleCount)
END) AS LastValue,
(CASE
WHEN ph.UTCDATE &gt;= @STARTDATE AND ph.UTCDATE &lt; @ENDDATE THEN SUM(SumValue)/SUM(SampleCount)
END) AS CurValue,
(CASE
WHEN ph.UTCDATE &gt;= @AVERAGEPERIODSTARTDATE AND ph.UTCDATE &lt; @STARTDATE THEN SUM(SumValue)/SUM(SampleCount)
END) AS AvgValue,
--Removing APM.GetDatePart replacing the execution by the code below.
--It boosts the overall performance as it reduces the number of calls of scalar function
CASE @GROUPBY
WHEN 'Hour' THEN Datepart(hh, DATEADD(mi, CAST(@TIMEZONE AS int), ph.UTCDate))
WHEN 'WeekDay' THEN Datepart(dw, DATEADD(mi, CAST(@TIMEZONE AS int), ph.UTCDate))
WHEN 'MonthDay' THEN Datepart(d, DATEADD(mi, CAST(@TIMEZONE AS int), ph.UTCDate))
END as Date,
(CASE WHEN @GROUPBY = 'WeekDay' THEN DatePart(Hour, DATEADD(mi, CAST(@TIMEZONE AS int), ph.UTCDate)) ELSE 0 END) AS Hours,
--hour is taken as DateDifference in day between 05/04/2009 9:00AM and 05/03/2009 9:00PM is one day,
--despite in case of @PERIOD = 'Day' it can be interpretated as one day (if 05/04/2009 9:00AM is end date), so difference should be taken as 0
ABS(DATEDIFF(hour, ph.UTCDATE, @ENDDATE)) / (@PERIODDAYSCOUNT*24) AS PeriodId
FROM
APM.PerfHourly AS ph (NOLOCK)
--Join with #SOURCEMACHINEFILTERTABLE with typeid = 1 provides filtering perfHourly by sourceid
JOIN #SOURCEMACHINEFILTERTABLE AS f1 ON (f1.TYPEID = 1 AND f1.VALUEID = ph.SOURCEID)
--Join with #SOURCEMACHINEFILTERTABLE with typeid = 2 provides filtering perfHourly by machineid
JOIN #SOURCEMACHINEFILTERTABLE AS f2 ON (f2.TYPEID = 2 AND f2.VALUEID = ph.MACHINEID)
WHERE
ph.UTCDATE &gt;= @AVERAGEPERIODSTARTDATE
AND ph.UTCDATE &lt; @ENDDATE
AND ph.PCTYPEID IN (@PROCESSORCOUNTERID, @IOCOUNTERID, @MEMORYCOUNTERID)
GROUP BY
ph.MACHINEID,
ph.SOURCEID,
ph.UTCDATE,
ph.PCTYPEID
)
,
--Calculate average source resource utilization for each resource type
--and for specified grouping period and date
ApplicationResourceUtilizationByMachines AS
(
SELECT
ph.MachineId,
ph.SourceId,
ph.PeriodId,
ph.Date,
ph.Hours,
-- Instance count should be same for different resource types in one hour for one process
-- and averaging them won't make any difference but allow to avoid one aggregation step
AVG(ph.CurInstanceCount) AS CurInstanceCount,
AVG(ph.LastInstanceCount) AS LastInstanceCount,
AVG(ph.AvgInstanceCount) AS AvgInstanceCount,

---------- Pivot resource by counter type -----------

----------- 'Process% Processor Time' counter -------------------
AVG(CASE WHEN ph.type = @PROCESSORCOUNTERID THEN ph.CurValue END) AS CurCPUSum,
AVG(CASE WHEN ph.type = @PROCESSORCOUNTERID THEN ph.LastValue END) AS LastCPUSum,
AVG(CASE WHEN ph.type = @PROCESSORCOUNTERID THEN ph.AvgValue END) AS AvgCPUSum,

----------- 'ProcessPrivate Bytes' counter -------------------
AVG(CASE WHEN ph.type = @MEMORYCOUNTERID THEN ph.CurValue END) AS CurMemSum,
AVG(CASE WHEN ph.type = @MEMORYCOUNTERID THEN ph.LastValue END) AS LastMemSum,
AVG(CASE WHEN ph.type = @MEMORYCOUNTERID THEN ph.AvgValue END) AS AvgMemSum,

----------- 'ProcessIO Data Bytes/sec' counter -------------------
AVG(CASE WHEN ph.type = @IOCOUNTERID THEN ph.CurValue END) AS CurIOSum,
AVG(CASE WHEN ph.type = @IOCOUNTERID THEN ph.LastValue END) AS LastIOSum,
AVG(CASE WHEN ph.type = @IOCOUNTERID THEN ph.AvgValue END) AS AvgIOSum
FROM
SourceHourlyResourceUtilization AS ph
GROUP BY
ph.MachineId,
ph.SourceId,
ph.PeriodId,
ph.Date,
ph.Hours
),
-- Count Monitored Requests and Avg. Request Time for Application on each machine
-- as source can run on different machines with same process name and app pool, but different sources set,
-- it is important to group by machine to, to avoid calculation of requests from the other app pool
-- Summarize request count in each period (PeriodId differs only for AvgValue)
ApplicationNetAppCountersByMachinePrepare AS
(
SELECT
ph.MACHINEID,
ph.SOURCEID,
----------------- Pivot Monitor Request Counter by period ------------------
CASE WHEN ph.UTCDATE &gt;= @LASTPERIODSTARTDATE AND ph.UTCDATE &lt; @STARTDATE
THEN SUM(CASE WHEN ph.PCTYPEID = @MONITOREDREQUESTCOUNTERID THEN ph.SUMVALUE END)
END AS LastMonRequest,
CASE WHEN ph.UTCDATE &gt;= @STARTDATE AND ph.UTCDATE &lt; @ENDDATE
THEN SUM(CASE WHEN ph.PCTYPEID = @MONITOREDREQUESTCOUNTERID THEN ph.SUMVALUE END)
END AS CurMonRequest,
CASE WHEN ph.UTCDATE &gt;= @AVERAGEPERIODSTARTDATE AND ph.UTCDATE &lt; @STARTDATE
THEN SUM(CASE WHEN ph.PCTYPEID = @MONITOREDREQUESTCOUNTERID THEN ph.SUMVALUE END)
END AS AvgMonRequest,

----------------- Pivot Avg. Request Time Counter by period ------------------
CASE WHEN ph.UTCDATE &gt;= @LASTPERIODSTARTDATE AND ph.UTCDATE &lt; @STARTDATE
THEN AVG(CASE WHEN ph.PCTYPEID = @REQUESTTIMECOUNTERID THEN ph.SUMVALUE / ph.SAMPLECOUNT END)
END AS LastAvgReqTime,
CASE WHEN ph.UTCDATE &gt;= @STARTDATE AND ph.UTCDATE &lt; @ENDDATE
THEN AVG(CASE WHEN ph.PCTYPEID = @REQUESTTIMECOUNTERID THEN ph.SUMVALUE / ph.SAMPLECOUNT END)
END AS CurAvgReqTime,
CASE WHEN ph.utcdate &gt;= @AVERAGEPERIODSTARTDATE AND ph.utcdate &lt; @STARTDATE
THEN AVG(CASE WHEN ph.PCTYPEID = @REQUESTTIMECOUNTERID THEN ph.SUMVALUE / ph.SAMPLECOUNT END)
END AS AvgReqTime,
--Removing APM.GetDatePart replacing the execution by the code below.
--It boosts the overall performance as it reduces the number of calls of scalar function
CASE @GROUPBY
WHEN 'Hour' THEN Datepart(hh, DATEADD(mi, CAST(@TIMEZONE AS int), ph.UTCDATE))
WHEN 'WeekDay' THEN Datepart(dw, DATEADD(mi, CAST(@TIMEZONE AS int), ph.UTCDATE))
WHEN 'MonthDay' THEN Datepart(d, DATEADD(mi, CAST(@TIMEZONE AS int), ph.UTCDATE))
END as Date,
(CASE WHEN @GROUPBY = 'WeekDay' THEN DatePart(Hour, DATEADD(mi, CAST(@TIMEZONE AS int), ph.UTCDATE)) ELSE 0 END) AS Hours,
--hour is taken as DateDifference in day between 05/04/2009 9:00AM and 05/03/2009 9:00PM is one day,
--despite in case of @PERIOD = 'Day' it can be interpretated as one day (if 05/04/2009 9:00AM is end date), so difference should be taken as 0
ABS(DATEDIFF(hour, ph.UTCDATE, @ENDDATE)) / (@PERIODDAYSCOUNT*24) AS PeriodId
FROM
APM.PerfHourly AS ph (NOLOCK)
--Join with #SOURCEMACHINEFILTERTABLE provides filtering perfHourly by sourceid
JOIN #SOURCEMACHINEFILTERTABLE AS f1 ON (f1.TYPEID = 1 AND ph.SOURCEID = f1.VALUEID)
--Join with #SOURCEMACHINEFILTERTABLE provides filtering perfHourly by machineid
JOIN #SOURCEMACHINEFILTERTABLE AS f2 ON (f2.TYPEID = 2 AND f2.VALUEID = ph.MACHINEID)
WHERE
ph.UTCDATE &gt;= @AVERAGEPERIODSTARTDATE
AND ph.UTCDATE &lt; @ENDDATE
AND ph.PCTYPEID IN (@REQUESTTIMECOUNTERID, @MONITOREDREQUESTCOUNTERID)
GROUP BY
ph.MACHINEID,
ph.SOURCEID,
ph.UTCDATE
),
--Calculate average request time and sum request count for specified grouping period and date
ApplicationNetAppCountersByMachine AS
(
SELECT
ph.MachineId,
ph.SourceId,
ph.PeriodId,
ph.Date,
ph.Hours,
SUM(ph.LastMonRequest) AS LastMonRequest,
SUM(ph.CurMonRequest) AS CurMonRequest,
SUM(ph.AvgMonRequest) AS AvgMonRequest,
AVG(ph.LastAvgReqTime) AS LastAvgReqTime,
AVG(ph.CurAvgReqTime) AS CurAvgReqTime,
AVG(ph.AvgReqTime) AS AvgReqTime
FROM
ApplicationNetAppCountersByMachinePrepare ph
GROUP BY
ph.MachineId,
ph.SourceId,
ph.PeriodId,
ph.Date,
ph.Hours
),
-- Union .NET counters and process counters for period Id. Period Id differs only for average(last three months) values, so grouping only for them
PCountersGroupedByMachineId AS (
SELECT
pc.machineId,
pc.SourceId,
pc.Hours,
pc.date,

MAX(netApp.CurMonRequest) AS CurReqCount,
MAX(netApp.LastMonRequest) AS LastReqCount,
AVG(netApp.AvgMonRequest) AS AvgReqCount,

MAX(netApp.CurAvgReqTime) AS CurAvgReqTime,
MAX(netApp.LastAvgReqTime) AS LastAvgReqTime,
AVG(netApp.AvgReqTime) AS AvgReqTime,

MAX(pc.CurCPUSum) AS CurCPUSum,
MAX(pc.LastCPUSum) AS LastCPUSum,
AVG(pc.AvgCPUSum) AS AvgCPUSum,
MAX(pc.CurMemSum) AS CurMemSum,
MAX(pc.LastMemSum) AS LastMemSum,
AVG(pc.AvgMemSum) AS AvgMemSum,
MAX(pc.CurIOSum) AS CurIOSum,
MAX(pc.LastIOSum) AS LastIOSum,
AVG(pc.AvgIOSum) AS AvgIOSum
FROM ApplicationResourceUtilizationByMachines pc
LEFT JOIN ApplicationNetAppCountersByMachine AS netApp ON netApp.MachineId = pc.MachineId
AND netApp.SourceId = pc.SourceId AND netApp.PeriodId = netApp.PeriodId
AND netApp.Hours = pc.Hours AND netApp.Date = pc.Date
GROUP BY
pc.machineId,
pc.SourceId,
pc.Hours,
pc.date
),
-- Calculate average source resource utilization between machines
ActivePreparePCounters AS (
SELECT
pc.SourceId,
pc.Hours,
pc.date,
SUM(CurReqCount) AS CurReqCount,
SUM(LastReqCount) AS LastReqCount,
SUM(AvgReqCount) AS AvgReqCount,
AVG(CurAvgReqTime) AS CurAvgReqTime,
AVG(LastAvgReqTime) AS LastAvgReqTime,
AVG(AvgReqTime) AS AvgReqTime,
AVG(CurCPUSum / COALESCE(m.CPUCount, 1)) AS CurCPUSum,
AVG(LastCPUSum / COALESCE(m.CPUCount, 1) ) AS LastCPUSum,
AVG(AvgCPUSum / COALESCE(m.CPUCount, 1)) AS AvgCPUSum,


AVG(CurMemSum) AS CurMemSum,
AVG(LastMemSum) AS LastMemSum,
AVG(AvgMemSum) AS AvgMemSum,
AVG(CurIOSum) AS CurIOSum,
AVG(LastIOSum) AS LastIOSum,
AVG(AvgIOSum) AS AvgIOSum
FROM
PCountersGroupedByMachineId pc
JOIN APM.Machine AS m ON m.MACHINEID = pc.MachineId
GROUP BY
pc.SourceId,
pc.Hours,
pc.date
),
--Count events for the current, last and average period. PeriodId differs only for average
PrepareEventsAvg AS
(
SELECT
e.sourceid AS sourceid,
e.date,
e.hour,
e.PeriodId,
MAX(E.SeViewerAddress) AS SeViewerAddress,
COUNT(CASE WHEN e.eventdate &gt;= @STARTDATE AND e.eventdate &lt; @ENDDATE THEN eventid END) AS CurrentEventsCount,
COUNT(CASE WHEN e.eventdate &gt;= @LASTPERIODSTARTDATE AND e.eventdate &lt; @STARTDATE THEN eventid END) AS LasEventsCount,
COUNT(CASE WHEN E.eventdate &gt;= @AVERAGEPERIODSTARTDATE AND E.eventdate &lt; @STARTDATE THEN eventid END) AS AvgEventsCount
FROM
ActivityBreakdown_EventsFiltered AS e
GROUP BY
sourceid,
PeriodId,
e.date,
e.hour
),
Events AS
(
SELECT
e.sourceid AS sourceid,
e.date,
e.hour,
MAX(E.SeViewerAddress) AS SeViewerAddress,
--PeriodId differs only for average, so for current and last period it doesn't matter which agg function is taken
MAX(CurrentEventsCount) AS CurrentEventsCount,
MAX(LasEventsCount) AS LasEventsCount,
--Average counting is not included current period
AVG(AvgEventsCount) AS AvgEventsCount
FROM
PrepareEventsAvg AS e
GROUP BY
sourceid,
e.date,
e.hour
),
MachineCPUUndefinedFlag AS
(
SELECT
sf.SOURCEID,
MIN(COALESCE(m.CPUCOUNT, -1)) AS CPUUndefinedFlag
FROM
#PROCESSFORSOURCE AS sf
JOIN APM.Machine AS m (NOLOCK) ON sf.MACHINEID = m.MACHINEID
GROUP BY
sf.SOURCEID
)
SELECT
-- This fake fields is need to provide compatibility with SP ApplicationStatusDrillthrough
GetDate() AS ClientDate,
SourcesDates.date AS Date,
SourcesDates.Hours AS Hours,
SourcesDates.Sourceid,
SourcesDates.Source AS Source,
--Period is used to organize result values, for example if @PERIOD is Day and @ENDDATE = '05/06/2009 13:00',
--this value should put 23 hour of 05/05/2009 before 10 hour of 05/06/2009
(CASE
WHEN (SourcesDates.date - APM.GetDatePart(@GROUPBY, DATEADD(mi, CAST(@TIMEZONE AS int), @ENDDATE))
) &lt; 0 THEN 0
WHEN (SourcesDates.date - APM.GetDatePart(@GROUPBY, DATEADD(mi, CAST(@TIMEZONE AS int), @ENDDATE))
) &gt;= 0 THEN 1
END) AS Period,
COALESCE(pc.CurReqCount, 0) AS CurMonitoredRequestSum,
COALESCE(pc.LastReqCount, 0) AS LastMonitoredRequestSum,
COALESCE(pc.AvgReqCount, 0) AS AvgMonitoredRequestSum,
COALESCE(pc.CurAvgReqTime, 0) AS CurAvgReqTime,
COALESCE(pc.LastAvgReqTime, 0) AS LastAvgReqTime,
COALESCE(pc.AvgReqTime, 0) AS AvgReqTime,
COALESCE(pc.CurCPUSum, 0) AS CurCPUValue,
COALESCE(pc.lastCPUSum, 0) AS LastCPUValue,
COALESCE(pc.AvgCPUSum, 0) AS AvgValue,
COALESCE(pc.CurMemSum, 0) AS CurMemValue,
COALESCE(pc.LastMemSum, 0) AS LastMemValue,
COALESCE(pc.AvgMemSum, 0) AS AvgMemValue,
COALESCE(pc.CurIOSum, 0) AS CurIOValue,
COALESCE(pc.LastIOSum, 0) AS LastIOValue,
COALESCE(pc.AvgIOSum, 0) AS AvgIOValue,
COALESCE(e.CurrentEventsCount, 0) AS NewEventsCount,
COALESCE(e.LasEventsCount, 0) AS OldEventsCount,
COALESCE(e.AvgEventsCount, 0) AS AvgEventsCount,
-- cpuFlag.CPUUndefinedFlag is null for current source if there is no one process PCounter row
-- in PerfHourly table for specified period. If so there is no need to show message about it
COALESCE(cpuFlag.CPUUndefinedFlag, 1) AS CPUUndefinedFlag,
(CASE
WHEN (@GROUPBY = 'Hour' AND ((SourcesDates.date % 2) = 0)) THEN SourcesDates.date
WHEN (@GROUPBY = 'WeekDay' AND ((SourcesDates.Hours + 12) % 24) = 0) THEN SourcesDates.date
WHEN (@GROUPBY = 'MonthDay') THEN SourcesDates.date
ELSE -1
END) AS OutputDate,
CASE LEFT(AppPool.AppPoolInfo,1)
WHEN N'''' THEN N''
WHEN N'' THEN ''
ELSE REPLACE(LEFT(AppPool.AppPoolInfo, LEN(AppPool.AppPoolInfo)-1), N'''', N'')
END AS pool,
E.SeViewerAddress
FROM
SourcesDates
LEFT OUTER JOIN MachineCPUUndefinedFlag AS cpuFlag ON SourcesDates.Sourceid = cpuFlag.Sourceid
LEFT OUTER JOIN ActivePreparePCounters AS pc ON (pc.date = SourcesDates.date AND pc.SourceId = SourcesDates.Sourceid AND SourcesDates.Hours = pc.Hours)
LEFT OUTER JOIN Events AS e ON (e.date = SourcesDates.date AND e.Sourceid = SourcesDates.Sourceid AND e.hour = SourcesDates.Hours)
JOIN SourceAppPools AS AppPool ON (AppPool.Sourceid = SourcesDates.Sourceid)
ORDER BY
Source,
Period DESC,
Date,
Hours
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.Application_sync'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.Application_sync AS RETURN 1')
END
GO

/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: Application_sync */
/* USED IN: Synchronization of SE-Viewer.'Application' table. */
/* Call by Intercept Reporting Services */
/* INPUT PARAMETERS: */
/* @OBJECTKEYXML - xml package syncronization data */
/* @TRACELEVEL - trace level. Reserved. */
/* OUTPUT PARAMETERS: */
/* @ROWNOTAFFECTED - number of records from package which haven't been */
/* synchronized.Reserved. */
/* Note: */
/* If there are records which have not been transferred that they have been already */
/* transferred from other SEVIEWER database earlier. Any other reason will cause a */
/* exception at an insert */
/************************************************************************************/
ALTER PROCEDURE APM.Application_sync
@OBJECTKEYXML ntext,
@TRACELEVEL int,
@ROWNOTAFFECTED int output
AS
BEGIN
SET NOCOUNT ON

DECLARE
@ERRORIND bit
,@ERRORMESSAGE nvarchar(max)
,@ERRORNUMBER int
,@ERRORSEVERITY int
,@ERRORSTATE int
,@ERRORLINE int
,@ERRORPROCEDURE nvarchar(256)
,@ERRORMESSAGETEXT nvarchar(max)

SET @ERRORIND = 0

BEGIN TRY

SET @ROWNOTAFFECTED = 0

DECLARE
@EXECRESULT int
,@XMLDOCHANDLE int
,@ERROR_MESSAGE nvarchar(max)

EXEC @EXECRESULT = sp_xml_preparedocument @XMLDOCHANDLE OUTPUT, @OBJECTKEYXML
IF @EXECRESULT &lt;&gt; 0
BEGIN
SELECT @ERROR_MESSAGE = message FROM APM.messages WHERE id = 50002
RAISERROR(@ERROR_MESSAGE, 16, 1, 'Application_sync', @EXECRESULT)
END

DECLARE @APPLICATION TABLE (
application nvarchar(255) collate database_default NOT NULL
)

----Fill table from package
INSERT @APPLICATION (
application
)
SELECT
application
FROM OPENXML(@XMLDOCHANDLE, 'rows/row', 2) WITH (
application nvarchar(255) ) xml

EXEC sp_xml_removedocument @XMLDOCHANDLE

SET @XMLDOCHANDLE = NULL

--insert not existing applications
INSERT APM.application (application,type)
SELECT DISTINCT sync.application , 3
FROM @APPLICATION sync
WHERE NOT EXISTS (SELECT * FROM APM.application a WHERE (a.application = sync.application))

END TRY
BEGIN CATCH
IF (@@TRANCOUNT &gt; 0)
ROLLBACK TRAN

SELECT
@ERRORNUMBER = ERROR_NUMBER()
,@ERRORSEVERITY = ERROR_SEVERITY()
,@ERRORSTATE = ERROR_STATE()
,@ERRORLINE = ERROR_LINE()
,@ERRORPROCEDURE = ISNULL(ERROR_PROCEDURE(), '-')
,@ERRORMESSAGETEXT = ERROR_MESSAGE()

SET @ERRORIND = 1
END CATCH

IF @XMLDOCHANDLE IS NOT NULL
EXEC sp_xml_removedocument @XMLDOCHANDLE

-- report error if any
IF (@ERRORIND = 1)
BEGIN
DECLARE @ADJUSTEDERRORSEVERITY int

SET @ADJUSTEDERRORSEVERITY = CASE
WHEN @ERRORSEVERITY = 2601 OR @ERRORSEVERITY = 2627 THEN 0
WHEN @ERRORSEVERITY &gt; 18 THEN 18
ELSE @ERRORSEVERITY
END

SELECT @ERROR_MESSAGE = message FROM APM.Messages WHERE id = 50004
RAISERROR (@ERROR_MESSAGE, @ADJUSTEDERRORSEVERITY, 1
,@ERRORNUMBER
,@ERRORSEVERITY
,@ERRORSTATE
,@ERRORPROCEDURE
,@ERRORLINE
,@ERRORMESSAGETEXT
)
END
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.ApplicationSourceMachine_sync'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.ApplicationSourceMachine_sync AS RETURN 1')
END
GO

/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: ApplicationSourceMachine_sync */
/* USED IN: Synchronization of SE_VIEWER:'applicationsourcemachine' table. */
/* Call by Intercept Reporting Services */
/* INPUT PARAMETERS: */
/* @OBJECTKEYXML - xml package syncronization data */
/* @TRACELEVEL - trace level. Reserved. */
/* OUTPUT PARAMETERS: */
/* @ROWNOTAFFECTED - number of records from package which haven't been */
/* synchronized.Reserved. */
/* Note: */
/* If there are records which have not been transferred that they have been already */
/* transferred from other SEVIEWER database earlier. Any other reason will cause a */
/* exception at an insert */
/************************************************************************************/
ALTER PROCEDURE [APM].[ApplicationSourceMachine_sync]
@OBJECTKEYXML ntext,
@TRACELEVEL int,
@ROWNOTAFFECTED int output
AS
BEGIN
SET NOCOUNT ON

DECLARE
@ERRORIND bit
,@ERRORMESSAGE nvarchar(max)
,@ERRORNUMBER int
,@ERRORSEVERITY int
,@ERRORSTATE int
,@ERRORLINE int
,@ERRORPROCEDURE nvarchar(256)
,@ERRORMESSAGETEXT nvarchar(max)

SET @ERRORIND = 0

BEGIN TRY

SET @ROWNOTAFFECTED = 0

DECLARE
@EXECRESULT int
,@XMLDOCHANDLE int
,@ERROR_MESSAGE nvarchar(max)

EXEC @EXECRESULT = sp_xml_preparedocument @XMLDOCHANDLE OUTPUT, @OBJECTKEYXML
IF @EXECRESULT &lt;&gt; 0
BEGIN
SELECT @ERROR_MESSAGE = message FROM APM.messages WHERE id = 50002
RAISERROR(@ERROR_MESSAGE, 16, 1, 'ApplicationSourceMachine_sync', @EXECRESULT)
END

DECLARE @APPLICATIONSOURCEMACHINE TABLE (
application nvarchar(255) collate database_default NOT NULL,
source nvarchar(255) collate database_default ,
machine nvarchar(255) collate database_default
)

----Fill table from package
INSERT @APPLICATIONSOURCEMACHINE(
application,source,machine
)
SELECT
application,source,machinename
FROM OPENXML(@XMLDOCHANDLE, 'rows/row', 2) WITH (
application nvarchar(255),
source nvarchar(255),
machinename nvarchar(255) ) xml

EXEC sp_xml_removedocument @XMLDOCHANDLE

SET @XMLDOCHANDLE = NULL

DECLARE @ALLAPPID int
DECLARE @NEWMACHINES TABLE (machineId int)

----- machine can be removed using "Remove computers wizard" so it is need synchronize machines ----
INSERT APM.MACHINE (MACHINE) OUTPUT INSERTED.MACHINEID INTO @NEWMACHINES
SELECT DISTINCT machine FROM @APPLICATIONSOURCEMACHINE app
WHERE NOT EXISTS (SELECT * FROM APM.machine m (NOLOCK) WHERE m.machine = app.machine) AND app.machine IS NOT NULL

IF EXISTS(SELECT * FROM @NEWMACHINES)
BEGIN
IF @ALLAPPID IS NULL
SELECT @ALLAPPID = APPLICATIONID FROM APM.APPLICATION (NOLOCK) WHERE APPLICATION = N'All'
---- it is need to create the links with 'All' application group for new sources
INSERT APM.APPLICATIONSOURCEMACHINE
( APPLICATIONID ,
SOURCEID ,
MACHINEID
)
SELECT
@ALLAPPID
,s.SourceId
,m.machineId
FROM
APM.SOURCE (NOLOCK) AS s
CROSS JOIN @NEWMACHINES as m
WHERE
NOT EXISTS
(
SELECT * FROM APM.APPLICATIONSOURCEMACHINE (NOLOCK) AS a
WHERE a.SOURCEID = s.sourceId AND a.APPLICATIONID = @ALLAPPID AND m.machineId = a.machineid
)
END

----- sources can be removed using "Remove applications wizard" so it is need synchronize sources ----
DECLARE @NEWSOURCES TABLE (sourceid int)

----- sources can be removed using "Remove applications wizard" so it is need synchronize sources ----
INSERT APM.SOURCE (SOURCE) OUTPUT INSERTED.SOURCEID INTO @NEWSOURCES
SELECT DISTINCT source FROM @APPLICATIONSOURCEMACHINE app
WHERE NOT EXISTS (SELECT * FROM APM.source s (NOLOCK) WHERE s.source = app.source) AND app.source IS NOT NULL

IF EXISTS(SELECT * FROM @NEWSOURCES)
BEGIN
IF @ALLAPPID IS NULL
SELECT @ALLAPPID = APPLICATIONID FROM APM.APPLICATION (NOLOCK) WHERE APPLICATION = N'All'
---- it is need to create the links with 'All' application group for new machines
INSERT APM.APPLICATIONSOURCEMACHINE
( APPLICATIONID ,
SOURCEID ,
MACHINEID
)
SELECT
@ALLAPPID
,s.sourceid
,m.machineId
FROM
APM.MACHINE (NOLOCK) AS m
CROSS JOIN @NEWSOURCES as s
WHERE
NOT EXISTS
(
SELECT * FROM APM.APPLICATIONSOURCEMACHINE (NOLOCK) AS a
WHERE a.SOURCEID = s.sourceid AND a.APPLICATIONID = @ALLAPPID AND m.MACHINEid = a.machineid
)
END

--insert not existing rows
--don't transfers rows with source is not found or machine is not found
INSERT APM.applicationsourcemachine (applicationid,sourceid,machineid)
SELECT DISTINCT a.applicationid,s.sourceid,m.machineid
FROM @APPLICATIONSOURCEMACHINE sync
JOIN APM.Application a ON a.application = sync.application
JOIN APM.Source s ON s.source = sync.source
JOIN APM.Machine m ON m.machine = sync.machine
WHERE NOT EXISTS ( SELECT * FROM APM.applicationsourcemachine asm
WHERE ( asm.applicationid = a.applicationid AND
asm.sourceid = s.sourceid AND
asm.machineid = m.machineid
))

END TRY
BEGIN CATCH
IF (@@TRANCOUNT &gt; 0)
ROLLBACK TRAN

SELECT
@ERRORNUMBER = ERROR_NUMBER()
,@ERRORSEVERITY = ERROR_SEVERITY()
,@ERRORSTATE = ERROR_STATE()
,@ERRORLINE = ERROR_LINE()
,@ERRORPROCEDURE = ISNULL(ERROR_PROCEDURE(), '-')
,@ERRORMESSAGETEXT = ERROR_MESSAGE()

SET @ERRORIND = 1
END CATCH

IF @XMLDOCHANDLE IS NOT NULL
EXEC sp_xml_removedocument @XMLDOCHANDLE

-- report error if any
IF (@ERRORIND = 1)
BEGIN
DECLARE @ADJUSTEDERRORSEVERITY int

SET @ADJUSTEDERRORSEVERITY = CASE
WHEN @ERRORSEVERITY = 2601 OR @ERRORSEVERITY = 2627 THEN 0
WHEN @ERRORSEVERITY &gt; 18 THEN 18
ELSE @ERRORSEVERITY
END

SELECT @ERROR_MESSAGE = message FROM APM.Messages WHERE id = 50004
RAISERROR (@ERROR_MESSAGE, @ADJUSTEDERRORSEVERITY, 1
,@ERRORNUMBER
,@ERRORSEVERITY
,@ERRORSTATE
,@ERRORPROCEDURE
,@ERRORLINE
,@ERRORMESSAGETEXT
)
END
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.SummaryQualityAnalysis'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.SummaryQualityAnalysis AS RETURN 1')
END
GO

/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: SummaryQualityAnalysis */
/* USED IN: SummaryQualityAnalysisSubReport.rdl */
/* INPUT PARAMETERS: */
/* @SOURCEID - Source id */
/* @COMPUTERIDS - List of the computer id, separated by comma. Exp: '1,2,3' */
/* @STARTDATE - Start date of the period */
/* @ENDDATE - End date of the period */
/* @TRESHOLD - Event duration treshold */
/* @PROBLEM - Event problem type (all, critical) */
/************************************************************************************/
ALTER PROCEDURE [APM].[SummaryQualityAnalysis]
@SOURCEID NVARCHAR(255),
@COMPUTERIDS NVARCHAR(MAX),
@STARTDATE DATETIME,
@ENDDATE DATETIME,
@THRESHOLD INT,
@PROBLEM NVARCHAR(10),
@PMSTATUS NVARCHAR(50) WITH RECOMPILE
AS
BEGIN
/************************************************************************************/
/* ASSISTING TEMP TABLES */
/************************************************************************************/



-- Filter table, which contains machine ids and source ids
-- typeid defines filter type - 1 for source and 2 for machine
-- valueId filter value - source id and machine id
CREATE TABLE #SOURCEMACHINEFILTERTABLE(
TYPEID INT,
VALUEID INT
)

-- Fill table #SOURCEMACHINEFILTERTABLE
INSERT
INTO #SOURCEMACHINEFILTERTABLE
SELECT
p.typeId AS TYPEID,
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@SOURCEID, @COMPUTERIDS) AS p

-- Filter table, which contains PM Statuses of Events
CREATE TABLE #PMSTATUSFILTERTABLE(
VALUEID INT
)

-- Fill table #PMSTATUSFILTERTABLE
INSERT
INTO #PMSTATUSFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@PMSTATUS, N'') AS p

CREATE TABLE #SUMMARYQUALITYANALYSISTMP
(
ID int,
RESOURCE nvarchar(255) collate database_default,
RESTYPE nvarchar(50) collate database_default,
RESCOUNT int,
FAILCOUNT int,
CONNCOUNT int,
PERFCOUNT int,
SECCOUNT int
)

INSERT INTO #SUMMARYQUALITYANALYSISTMP
SELECT
ROW_NUMBER() OVER (ORDER BY COUNT(e.eventid) desc) AS ID,
r.resourceuri AS RESOURCE,
rg.name AS RESTYPE,
COUNT(e.eventid) AS RESCOUNT,
COUNT(CASE aspect WHEN 'applicationfailure' THEN 1 END) AS FAILCOUNT,
COUNT(CASE aspect WHEN 'connectivity' THEN 1 END) AS CONNCOUNT,
COUNT(CASE aspect WHEN 'performance' THEN 1 END) AS PERFCOUNT,
COUNT(CASE aspect WHEN 'security' THEN 1 END) AS SECCOUNT
FROM
APM.event AS e (NOLOCK)
JOIN APM.resource AS r (NOLOCK) on e.resourceid = r.resourceid
JOIN APM.resourcegroup AS rg (NOLOCK) on r.resourcegroupid = rg.resourcegroupid
JOIN #SOURCEMACHINEFILTERTABLE AS f ON (f.TYPEID = 2 AND f.VALUEID = e.MachineId)
JOIN #PMSTATUSFILTERTABLE AS f3 ON (f3.VALUEID = e.PMStatus)
WHERE
((e.aspect = 'performance' AND e.eventduration / 1000000.0 &gt;= @THRESHOLD) OR
e.aspect IN ('applicationfailure', 'connectivity', 'security'))
AND (e.HeavyLight &lt;&gt; 0 OR e.HeavyLight IS NULL)
AND e.sourceId = @SOURCEID
AND e.utceventdate &gt;= @STARTDATE AND e.utceventdate &lt; @ENDDATE
AND (e.category LIKE @PROBLEM OR e.category IS NULL)

GROUP BY
r.resourceuri, rg.name

/*------------------ Base query -------------------------- */
SELECT TOP 5
R1.ID,
R1.RESOURCE,
R1.RESTYPE as RESTYPE,
R1.RESCOUNT,
R1.FAILCOUNT,
R1.CONNCOUNT,
R1.SECCOUNT,
R1.PERFCOUNT,
R1.RESCOUNT + (
SELECT CASE WHEN SUM(r2.RESCOUNT) IS NULL THEN 0 ELSE SUM(r2.RESCOUNT) END
FROM #SUMMARYQUALITYANALYSISTMP r2
WHERE r2.ID &lt; r1.ID
) AS runValue,
SUM(RESCOUNT) OVER() AS AllCount
FROM
#SUMMARYQUALITYANALYSISTMP AS R1
ORDER BY
ID
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.SummarySizeAnalysisReport'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.SummarySizeAnalysisReport AS RETURN 1')
END
GO

/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: SummarySizeAnalysisReport */
/* USED IN: Summary Size Analysis Report */
/* INPUT PARAMETERS: */
/* @STARTDATE - Start date of the priod */
/* @ENDDATE - End date of the period */
/* @SOURCEIDS - List of source Id, separated by comma. Exp: '1,2,3' */
/* @MACHINEIDS - List of machine Id, separated by comma. Exp: '4,5,6' */
/* @ORDERBY - Specifies field to which sorting should be applayed */
/* 1. Page Content Size */
/* 2. Ajax Size */
/* 3. Total Size */
/* 4. Event Count */
/* 5. Event Duration */
/************************************************************************************/
ALTER PROCEDURE APM.SummarySizeAnalysisReport
@STARTDATE DATETIME,
@ENDDATE DATETIME,
@SOURCEIDS NVARCHAR(MAX),
@MACHINEIDS NVARCHAR(MAX),
@ORDERBY INT,
@PMSTATUS NVARCHAR(50)
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON

/****************************************************************************************/
/* ASSISTING TEMP TABLES */
/****************************************************************************************/

-- Filter table, which contains machine ids and source ids
-- typeid defines filter type - 1 for source and 2 for machine
-- valueId filter value - source id and machine id
CREATE TABLE #SOURCEMACHINEFILTERTABLE(
TYPEID INT,
VALUEID INT
)

-- Fill table #SOURCEMACHINEFILTERTABLE
INSERT
INTO #SOURCEMACHINEFILTERTABLE
SELECT
p.typeId AS TYPEID,
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@SOURCEIDS, @MACHINEIDS) AS p

-- Filter table, which contains PM Statuses of Events
CREATE TABLE #PMSTATUSFILTERTABLE(
VALUEID INT
)

-- Fill table #PMSTATUSFILTERTABLE
INSERT
INTO #PMSTATUSFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@PMSTATUS, N'') AS p

CREATE TABLE #CLIENTEVENT
(
CSEVENTID INT,
SOURCEID INT
)

INSERT INTO #CLIENTEVENT
SELECT
CSEVENTID,
SOURCEID
FROM
APM.CSEvent (NOLOCK) AS e
JOIN #SOURCEMACHINEFILTERTABLE AS f1 ON (f1.VALUEID = e.SOURCEID AND f1.TYPEID = 1)
JOIN #SOURCEMACHINEFILTERTABLE AS f2 ON (f2.VALUEID = e.MACHINEID AND f2.TYPEID = 2)
JOIN #PMSTATUSFILTERTABLE AS f3 ON (f3.VALUEID = e.PMSTATUS)
WHERE
e.PAGEURI IS NOT NULL
AND e.CLASSTYPE = N'Performance'
AND e.UTCDATE &gt;= @STARTDATE
AND e.UTCDATE &lt; @ENDDATE

/****************************************************************************************/
/* MAIN QUERY */
/****************************************************************************************/
;WITH AJAXEvents AS
(
SELECT
e.CSEVENTID,
e.SOURCEID,
0 AS IsPageEvent,
ajax.TOTALTIME AS TotalTime,
ajax.RESPONSESIZE + ajax.REQUESTSIZE AS TotalSize
FROM
#CLIENTEVENT AS e
JOIN APM.CSAJAX AS ajax (NOLOCK) ON e.CSEVENTID = ajax.CSEVENTID
),
JSEvents AS
(
SELECT
e.CSEVENTID,
e.SOURCEID,
0 AS IsPageEvent,
js.TOTALTIME AS TotalTime,
NULL AS TotalSize
FROM
#CLIENTEVENT AS e
JOIN APM.CSJSCRIPTEVENT AS js (NOLOCK) ON e.CSEVENTID = js.CSEVENTID
),
PageEvents AS
(
SELECT
e.CSEVENTID,
e.SOURCEID,
1 AS IsPageEvent,
p.TOTALTIME AS TotalTime,
p.TOTALSIZE AS TotalSize
FROM
#CLIENTEVENT AS e
JOIN APM.CSPageEvent AS p (NOLOCK) ON e.CSEVENTID = p.CSEVENTID
),
UnionEvents AS
(
SELECT * FROM AJAXEvents
UNION ALL
SELECT * FROM JSEvents
UNION ALL
SELECT * FROM PageEvents
),
EventAggregation AS
(
SELECT
SOURCEID,
CSEVENTID,
MAX(IsPageEvent) AS IsPageEvent,
MAX(TotalTime) AS TotalTime,
SUM(TotalSize) AS TotalSize
FROM
UnionEvents
GROUP BY
SOURCEID,
CSEVENTID
),
SourceAggregation AS
(
SELECT
SOURCEID,
COUNT(*) AS EventCount,
AVG(TotalTime) / 1000.0 AS EventDuration,
-- Take into account AJAX call size, which occured during page load event
AVG(CASE WHEN IsPageEvent = 1 THEN TotalSize END) / 1024.0 AS PageContentSize,
AVG(TotalSize) / 1024.0 AS TotalSize,
-- Calculate AJAX size only for JS with AJAX and for Asynch AJAX events
AVG(CASE WHEN IsPageEvent = 0 THEN TotalSize END) / 1024.0 AS AjaxSize
FROM
EventAggregation
GROUP BY
SOURCEID
)
SELECT TOP(10)
Row_Number() OVER(ORDER BY
CASE
WHEN @ORDERBY = 1 THEN ds.PageContentSize
WHEN @ORDERBY = 2 THEN ds.AjaxSize
WHEN @ORDERBY = 3 THEN ds.TotalSize
WHEN @ORDERBY = 4 THEN ds.EventCount
WHEN @ORDERBY = 5 THEN ds.EventDuration
END DESC) AS Id,
ds.SOURCEID,
s.SOURCE,
ds.EventCount,
ds.EventDuration,
ds.PageContentSize,
ds.TotalSize,
ds.AjaxSize
FROM
SourceAggregation AS ds
JOIN APM.Source AS s (NOLOCK) ON s.SOURCEID = ds.SOURCEID
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.SummarySizeAnalysisTopAJAXSubReport'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.SummarySizeAnalysisTopAJAXSubReport AS RETURN 1')
END
GO

/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: SummarySizeAnalysisTopAJAXSubReport */
/* USED IN: Summary Size Analysis Sub Report for top AJAX call */
/* INPUT PARAMETERS: */
/* @STARTDATE - Start date of the priod */
/* @ENDDATE - End date of the period */
/* @SOURCEID - Source Id */
/* @MACHINEIDS - List of machine Id, separated by comma. Exp: '4,5,6' */
/************************************************************************************/
ALTER PROCEDURE APM.SummarySizeAnalysisTopAJAXSubReport
@STARTDATE DATETIME,
@ENDDATE DATETIME,
@SOURCEID NVARCHAR(MAX),
@MACHINEIDS NVARCHAR(MAX),
@PMSTATUS NVARCHAR(50)
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON

/****************************************************************************************/
/* ASSISTING TEMP TABLES */
/****************************************************************************************/

-- Filter table, which contains machine ids
-- valueId filter value for machineId
CREATE TABLE #MACHINEFILTERTABLE(
TYPEID INT,
VALUEID INT
)

-- Fill table #SOURCEMACHINEFILTERTABLE
INSERT
INTO #MACHINEFILTERTABLE
SELECT
p.typeId AS TYPEID,
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@MACHINEIDS, N'') AS p

-- Filter table, which contains PM Statuses of Events
CREATE TABLE #PMSTATUSFILTERTABLE(
VALUEID INT
)

-- Fill table #PMSTATUSFILTERTABLE
INSERT
INTO #PMSTATUSFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@PMSTATUS, N'') AS p

CREATE TABLE #AJAXEVENT
(
CSEVENTID INT,
PAGEURI NVARCHAR(255) collate database_default,
AJAXURI NVARCHAR(255) collate database_default,
AJAXDURATION DECIMAL(35, 0),
RESPONSESIZE BIGINT,
REQUESTSIZE BIGINT
)

INSERT INTO #AJAXEVENT
SELECT
e.CSEventId,
e.PageUri,
ajax.Uri,
ajax.TotalTime,
ajax.ResponseSize,
ajax.REQUESTSIZE
FROM
APM.CSEvent (NOLOCK) AS e
JOIN #MACHINEFILTERTABLE AS f ON f.VALUEID = e.MACHINEID
JOIN #PMSTATUSFILTERTABLE AS f1 ON (f1.VALUEID = e.PMSTATUS)
CROSS APPLY (
SELECT TOP(1)
ajax.Uri,
ajax.TotalTime,
ajax.RESPONSESIZE,
ajax.REQUESTSIZE
FROM
APM.CSAJAX AS ajax (NOLOCK)
WHERE
ajax.CSEVENTID = e.CSEVENTID
ORDER BY
ajax.TOTALTIME DESC
) AS ajax
WHERE
e.CLASSTYPE = N'Performance'
AND e.SOURCEID = @SOURCEID
AND e.UTCDATE &gt;= @STARTDATE
AND e.UTCDATE &lt; @ENDDATE
-- collected ajax calls except for page sync ajax calls
AND e.EVENTCLASS &lt;&gt; N'CSMPMonitorLog'

CREATE INDEX idx_Event ON #AJAXEVENT (CSEVENTID)

/****************************************************************************************/
/* MAIN QUERY */
/****************************************************************************************/
;WITH EventDuration AS
(
SELECT
a.CSEVENTID,
a.PAGEURI,
a.AJAXURI,
a.AJAXDURATION AS AJAXDuration,
a.RESPONSESIZE,
a.REQUESTSIZE
FROM
#AJAXEVENT AS a
LEFT OUTER JOIN APM.CSJScriptEvent AS js (NOLOCK) ON a.CSEVENTID = js.cseventid
),
AJAXSize AS
(
SELECT
COUNT(CSEventId) AS EventCount,
PageUri,
AJAXUri,
AVG(AJAXDuration) AS AJAXDuration,
AVG(ResponseSize) AS ResponseSize,
AVG(RequestSize) AS RequestSize,
AVG(ResponseSize + RequestSize) AS TotalSize
FROM
EventDuration
GROUP BY
PageUri,
AJAXUri
),
NumberedRow AS
(
SELECT
Row_Number() OVER(ORDER BY TotalSize DESC) AS Id,
EventCount,
PageUri,
AJAXUri,
AJAXDuration/1000.0 AS AJAXDuration,
ResponseSize/1024.0 AS ResponseSize,
RequestSize/1024.0 AS RequestSize,
TotalSize/1024.0 AS TotalSize,
SUM(EventCount) OVER() AS TotalEventCount
FROM
AJAXSize
)
SELECT TOP(4)
Id,
EventCount,
PageUri,
AJAXUri AS AjaxCall,
AJAXDuration,
ResponseSize,
RequestSize,
TotalSize,
TotalEventCount
FROM
NumberedRow
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.SummarySizeAnalysisTopPagesSubReport'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.SummarySizeAnalysisTopPagesSubReport AS RETURN 1')
END
GO

/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: SummarySizeAnalysisTopPagesSubReport */
/* USED IN: Summary Size Analysis Sub Report for top pages */
/* INPUT PARAMETERS: */
/* @STARTDATE - Start date of the priod */
/* @ENDDATE - End date of the period */
/* @SOURCEID - Source Id */
/* @MACHINEIDS - List of machine Id, separated by comma. Exp: '4,5,6' */
/* @ORDERBY - Specifies field to which sorting should be applayed */
/* 1. Image Size */
/* 2. CssStyle Size */
/* 3. Htc Size */
/* 4. Script Size */
/* 5. HTML Size */
/* 6. AjaxSize Size */
/* 7. TotalSize Size */
/* 8. Event Count */
/* 9. Avg. Event Duration */
/************************************************************************************/
ALTER PROCEDURE APM.SummarySizeAnalysisTopPagesSubReport
@STARTDATE DATETIME,
@ENDDATE DATETIME,
@SOURCEID INT,
@MACHINEIDS NVARCHAR(MAX),
@ORDERBY INT,
@PMSTATUS NVARCHAR(50)
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON

/****************************************************************************************/
/* ASSISTING TEMP TABLES */
/****************************************************************************************/

-- Filter table, which contains machine ids
-- valueId filter value for machineid
CREATE TABLE #MACHINEFILTERTABLE(
VALUEID INT
)

-- Fill table #SOURCEMACHINEFILTERTABLE
INSERT
INTO #MACHINEFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@MACHINEIDS, N'') AS p

-- Filter table, which contains PM Statuses of Events
CREATE TABLE #PMSTATUSFILTERTABLE(
VALUEID INT
)

-- Fill table #PMSTATUSFILTERTABLE
INSERT
INTO #PMSTATUSFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@PMSTATUS, N'') AS p

CREATE TABLE #PAGEEVENT
(
CSEVENTID INT,
PAGEURI NVARCHAR(255) collate database_default,
TOTALTIME DECIMAL(35, 0),
TOTALSIZE DECIMAL(35, 0)
)

INSERT INTO #PAGEEVENT
SELECT
e.CSEVENTID,
e.PAGEURI,
P.TOTALTIME,
P.TOTALSIZE
FROM
APM.CSEvent (NOLOCK) AS e
JOIN #MACHINEFILTERTABLE AS f ON (f.VALUEID = e.MACHINEID)
JOIN #PMSTATUSFILTERTABLE AS f1 ON (f1.VALUEID = e.PMSTATUS)
JOIN APM.CSPageEvent AS p (NOLOCK) ON p.CSEventId = e.CSEVENTID
WHERE
e.PAGEURI IS NOT NULL
AND e.SOURCEID = @SOURCEID
AND e.CLASSTYPE = N'Performance'
AND e.SOURCEID &lt;&gt; -1
AND e.UTCDATE &gt;= @STARTDATE
AND e.UTCDATE &lt; @ENDDATE

/****************************************************************************************/
/* MAIN QUERY */
/****************************************************************************************/
--Before grouping by page uri, event content with Null size should by transformed to 0,
-- to provide convergence with Avg total size
;WITH PeripheralSize AS
(
SELECT
e.CSEVENTID,
SUM(CASE WHEN p.TYPE = N'Image' THEN p.TotalSize END) AS Image,
SUM(CASE WHEN p.TYPE = N'Script' THEN p.TotalSize END) AS Script,
SUM(CASE WHEN p.TYPE = N'CssStyle' THEN p.TotalSize END) AS CssStyle,
SUM(CASE WHEN p.TYPE = N'HtcBehavior' THEN p.TotalSize END) AS HtcBehavior,
SUM(CASE WHEN p.TYPE = N'HTML' THEN p.TotalSize END) AS HTML
FROM
APM.CSPeripheral AS p (NOLOCK)
JOIN #PAGEEVENT AS e ON p.cseventid = e.CSEVENTID
GROUP BY
e.CSEVENTID
),
PageSize AS
(
SELECT
e.PAGEURI,
COUNT(e.CSEVENTID) AS EventCount,
AVG(COALESCE(p.Image, 0)) AS Image,
AVG(COALESCE(p.Script, 0)) AS Script,
AVG(COALESCE(p.CssStyle, 0)) AS CssStyle,
AVG(COALESCE(p.HtcBehavior, 0)) AS HtcBehavior,
AVG(COALESCE(p.HTML, 0)) AS HTML,
AVG(e.TOTALTIME) AS EventDuration,
AVG(e.TOTALSIZE) AS TotalSize
FROM
#PAGEEVENT AS e
LEFT OUTER JOIN PeripheralSize AS p ON p.CSEventid = e.CSEVENTID
GROUP BY
e.PAGEURI
),
AJAXSize AS
(
SELECT
a.PageUri,
AVG(a.AjaxSize) AS AjaxSize
FROM
(
SELECT
e.CSEVENTID,
e.PAGEURI,
SUM(COALESCE(ajax.ResponseSize + ajax.REQUESTSIZE, 0)) AS AjaxSize
FROM
#PAGEEVENT AS e
JOIN APM.CSAJAX AS ajax (NOLOCK) ON (ajax.CSEventId = e.CSEVENTID)
GROUP BY
e.CSEVENTID,
e.PAGEURI
) AS a
GROUP BY
a.PageUri
),
NumberedResults AS
(
SELECT
Row_Number() OVER(ORDER BY
CASE
WHEN @ORDERBY = 1 THEN p.Image
WHEN @ORDERBY = 2 THEN p.CssStyle
WHEN @ORDERBY = 3 THEN p.HtcBehavior
WHEN @ORDERBY = 4 THEN p.Script
WHEN @ORDERBY = 5 THEN p.HTML
WHEN @ORDERBY = 6 THEN ajax.AjaxSize
WHEN @ORDERBY = 7 THEN p.TotalSize + COALESCE(ajax.AjaxSize, 0)
WHEN @ORDERBY = 8 THEN p.EventCount
WHEN @ORDERBY = 9 THEN p.EventDuration
END DESC) AS Id,
p.PageUri,
p.EventCount,
p.Image/(1024.0) AS Image,
p.Script/(1024.0) AS Script,
p.CssStyle/(1024.0) AS CssStyle,
p.HtcBehavior/(1024.0) AS HtcBehavior,
p.HTML/(1024.0) AS HTML,
p.EventDuration/(1000.0) AS EventDuration,
(p.TotalSize + COALESCE(ajax.AjaxSize, 0))/(1024.0) AS TotalSize,
COALESCE(ajax.AjaxSize, 0)/(1024.0) AS AjaxSize,
SUM(p.EventCount) OVER() AS TotalEventCount
FROM
PageSize AS p
LEFT OUTER JOIN AJAXSize AS ajax ON Ajax.PageUri = p.PageUri
)
SELECT TOP(4)
Id,
PageUri,
EventCount,
Image,
Script,
CssStyle,
HtcBehavior,
HTML,
EventDuration,
TotalSize,
AjaxSize,
TotalEventCount
FROM
NumberedResults
ORDER BY
Id
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.TopUserPerformanceIssues'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.TopUserPerformanceIssues AS RETURN 1')
END
GO

/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: TopUserPerformanceIssues */
/* USED IN: Top5UserPerformanceSubReport.rdl */
/* INPUT PARAMETERS: */
/* @SOURCEID - Source id */
/* @COMPUTERIDS - List of the computer id, separated by comma. Exp: '1,2,3' */
/* @STARTDATE - Start date of the period */
/* @ENDDATE - End date of the period */
/* @TRESHOLD - Event duration treshold */
/************************************************************************************/
ALTER PROCEDURE [APM].[TopUserPerformanceIssues]
(
@SOURCEIDS NVARCHAR(MAX),
@COMPUTERIDS NVARCHAR(MAX),
@STARTDATE DATETIME,
@ENDDATE DATETIME,
@THRESHOLD INT,
@USERNAME NVARCHAR(255),
@PMSTATUS NVARCHAR(50)
) WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON

/************************************************************************************/
/* ASSISTING TEMP TABLES */
/************************************************************************************/

-- Filter table, which contains machine ids and source ids
-- typeid defines filter type - 1 for source and 2 for machine
-- valueId filter value - source id and machine id
CREATE TABLE #SOURCEMACHINEFILTERTABLE(
TYPEID INT,
VALUEID INT
)

-- Fill table #SOURCEMACHINEFILTERTABLE
INSERT
INTO #SOURCEMACHINEFILTERTABLE
SELECT
p.typeId AS TYPEID,
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@SOURCEIDS, @COMPUTERIDS) AS p

-- Filter table, which contains PM Statuses of Events
CREATE TABLE #PMSTATUSFILTERTABLE(
VALUEID INT
)

-- Fill table #PMSTATUSFILTERTABLE
INSERT
INTO #PMSTATUSFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@PMSTATUS, N'') AS p

CREATE TABLE #SUMUSERANALYSIS
(
DESCRIPTION nvarchar(255) collate database_default,
USERID int,
USERFLAG BIT,
SOURCEID int,
EVENTCOUNT int,
USERSUMSLOWESTNODEDUR decimal(35,0),
USERCOUNTSLOWESTNODEDUR int,
SLOWESTNODEDUR decimal(35,0),
COUNTSLOWESTNODDUR int
)

-- Select performance event information for all users
;WITH UsersInfo AS
(
SELECT
pn.description AS Description,
MIN(e.UserId) AS UserId,
CASE u.Name WHEN @USERNAME THEN 1 ELSE 0 END AS UserFlag,
e.sourceId,
COUNT(e.EVENTID) AS EventCount,
SUM(CASE u.Name WHEN @USERNAME THEN pn.selfduration END) AS UserSumSlowestNodeDur,
COUNT(CASE u.Name WHEN @USERNAME THEN e.EVENTID END) AS UserCountSlowestNodeDur,
SUM(pn.selfduration) AS SlowestNodeDur,
COUNT(pn.selfduration) AS CountSlowestNodeDur
FROM
APM.EVENT AS e
JOIN #SOURCEMACHINEFILTERTABLE AS f1 ON (f1.TYPEID = 1 AND f1.VALUEID = e.SourceId)
JOIN #SOURCEMACHINEFILTERTABLE AS f2 ON (f2.TYPEID = 2 AND f2.VALUEID = e.MachineId)
JOIN #PMSTATUSFILTERTABLE AS f3 ON (f3.VALUEID = e.PMStatus)
CROSS APPLY(SELECT TOP(1) pn1.SelfDuration, pn1.Description
FROM
APM.PerformanceNode AS pn1
WHERE
pn1.eventid = e.eventid
AND pn1.resourceid = e.resourceid
ORDER BY
pn1.SelfDuration DESC) AS pn
JOIN APM.Users AS u ON e.userid = u.userid
WHERE
E.UTCEVENTDATE &gt; @STARTDATE
AND E.UTCEVENTDATE &lt; @ENDDATE
AND E.EVENTDURATION / 1000000.0 &gt;= @THRESHOLD
AND E.ASPECT = N'performance'
AND COALESCE(E.HeavyLight, 1) &lt;&gt; 0

GROUP BY
e.sourceid,
pn.description,
u.name
)
INSERT #SUMUSERANALYSIS
SELECT
DESCRIPTION,
USERID,
USERFLAG,
SOURCEID,
EVENTCOUNT,
USERSUMSLOWESTNODEDUR,
USERCOUNTSLOWESTNODEDUR,
SLOWESTNODEDUR,
COUNTSLOWESTNODEDUR
FROM UsersInfo

CREATE INDEX temp1_idx ON #SUMUSERANALYSIS(DESCRIPTION, SOURCEID) INCLUDE (USERID, EVENTCOUNT, SLOWESTNODEDUR)

-- Select information for current user
;WITH OrderedDataSet AS
(
SELECT
u.DESCRIPTION,
u.SOURCEID,
u.EVENTCOUNT,
CASE
WHEN u.USERCOUNTSLOWESTNODEDUR &lt;&gt;0 THEN u.USERSUMSLOWESTNODEDUR / (u.USERCOUNTSLOWESTNODEDUR * 1000)
ELSE 0
END AS SlowestNodeDur
FROM
#SUMUSERANALYSIS AS u
WHERE
u.USERFLAG = 1
),
--Select top 5 performance event for user
TopDataSet AS
(
SELECT TOP 5
ROW_NUMBER() OVER(ORDER BY EventCount DESC) AS id,
1 AS UserId,
description,
sourceId,
EventCount,
SlowestNodeDur,
EventCount AS SumEventCount,
SUM(EventCount) OVER() AS TotalEventCount,
0 AS UsersAffected
FROM
OrderedDataSet
),
-- Calculate information for all users, but only for top 5 performence events
EachUserInfo AS
(
SELECT
f.Id,
UserStat.DESCRIPTION,
UserStat.SOURCEID,
UserStat.EVENTCOUNT,
UserStat.SLOWESTNODEDUR,
UserStat.USERID
FROM
#SUMUSERANALYSIS UserStat
JOIN TopDataSet AS f ON (f.SOURCEID = UserStat.SOURCEID AND UserStat.DESCRIPTION = f.DESCRIPTION)
),
OtherUsersInfo AS
(
SELECT
MAX(Id) AS Id,
2 AS UserId,
description,
sourceId,
AVG(EventCount * 1.0) AS EventCount,
SUM(SlowestNodeDur)/1000.0/SUM(EventCount) AS SlowestNodeDur,
0 AS SumEventCount,
0 AS TotalEventCount,
COUNT(DISTINCT COALESCE(userid,0)) AS UsersAffected
FROM
EachUserInfo
GROUP BY
sourceId,
description
),
[Result] AS
(
SELECT *
FROM
TopDataSet
UNION
SELECT *
FROM
OtherUsersInfo
)
SELECT
r.Id,
r.UserId,
r.description,
s.Source,
r.EventCount,
r.SlowestNodeDur,
r.SumEventCount,
r.TotalEventCount,
r.UsersAffected
FROM
[Result] r
JOIN APM.Source (NOLOCK) AS s ON s.SourceId = r.SourceId
ORDER BY
Id, UserId
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.TopUserExceptionIssues'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.TopUserExceptionIssues AS RETURN 1')
END
GO

/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: TopUserExceptionIssues */
/* USED IN: Top5UserExceptionSubReport.rdl */
/* INPUT PARAMETERS: */
/* @SOURCEID - Source id */
/* @COMPUTERIDS - List of the computer id, separated by comma. Exp: '1,2,3' */
/* @STARTDATE - Start date of the period */
/* @ENDDATE - End date of the period */
/************************************************************************************/
ALTER PROCEDURE [APM].[TopUserExceptionIssues]
(
@SOURCEIDS NVARCHAR(MAX),
@COMPUTERIDS NVARCHAR(MAX),
@STARTDATE DATETIME,
@ENDDATE DATETIME,
@USERNAME NVARCHAR(255),
@PMSTATUS NVARCHAR(50)
) WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON
/************************************************************************************/
/* ASSISTING TEMP TABLES */
/************************************************************************************/

-- Filter table, which contains machine ids and source ids
-- typeid defines filter type - 1 for source and 2 for machine
-- valueId filter value - source id and machine id
CREATE TABLE #SOURCEMACHINEFILTERTABLE(
TYPEID INT,
VALUEID INT
)

-- Fill table #SOURCEMACHINEFILTERTABLE
INSERT
INTO #SOURCEMACHINEFILTERTABLE
SELECT
p.typeId AS TYPEID,
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@SOURCEIDS, @COMPUTERIDS) AS p

-- Filter table, which contains PM Statuses of Events
CREATE TABLE #PMSTATUSFILTERTABLE(
VALUEID INT
)

-- Fill table #PMSTATUSFILTERTABLE
INSERT
INTO #PMSTATUSFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@PMSTATUS, N'') AS p

CREATE TABLE #SUMUSERANALYSIS
(
DESCRIPTION nvarchar(255) collate database_default,
USERID int,
USERFLAG BIT,
SOURCEID int,
EVENTCOUNT int,
SECURITYFAILURE int,
APPLICATIONFAILURE int,
CONNECTIVITYFAILURE int
)

--Select information about events for all users
;WITH UsersInfo AS
(
SELECT
e.DESCRIPTION AS DESCRIPTION,
MIN(e.USERID) AS USERID,
CASE u.Name WHEN @USERNAME THEN 1 ELSE 0 END AS USERFLAG,
e.SOURCEID,
COUNT(e.EVENTID) AS EVENTCOUNT,
COUNT(CASE WHEN e.ASPECT = N'security' THEN e.EVENTID END) AS SECURITYFAILURE,
COUNT(CASE WHEN e.ASPECT = N'applicationfailure' THEN e.EVENTID END) AS APPLICATIONFAILURE,
COUNT(CASE WHEN e.ASPECT = N'connectivity' THEN e.EVENTID END) AS CONNECTIVITYFAILURE
FROM
APM.EVENT AS e
--JOIN ExceptionNode AS en ON (en.eventid = e.eventid and en.resourceid = e.resourceid)
JOIN #SOURCEMACHINEFILTERTABLE AS f1 ON (f1.TYPEID = 1 AND f1.VALUEID = e.SourceId)
JOIN #SOURCEMACHINEFILTERTABLE AS f2 ON (f2.TYPEID = 2 AND f2.VALUEID = e.MachineId)
JOIN #PMSTATUSFILTERTABLE AS f3 ON (f3.VALUEID = e.PMStatus)
JOIN APM.Users AS u ON e.USERID = u.USERID
WHERE
e.UTCEVENTDATE &gt; @STARTDATE
AND e.UTCEVENTDATE &lt; @ENDDATE
AND e.ASPECT IN ( N'security',N'applicationfailure',N'connectivity')

GROUP BY
e.SOURCEID,
e.DESCRIPTION,
u.NAME
)
INSERT #SUMUSERANALYSIS
SELECT
Description,
UserId,
UserFlag,
SourceId,
EventCount,
SecurityFailure,
ApplicationFailure,
ConnectivityFailure
FROM UsersInfo

CREATE INDEX temp1_idx ON #SUMUSERANALYSIS(DESCRIPTION, SOURCEID)

-- Select event information for current user only (condition UserFlag = 1 allows to filter event by current user)
;WITH OrderedDataSet AS
(
SELECT
ROW_NUMBER() OVER(ORDER BY EVENTCOUNT DESC) AS ID,
DESCRIPTION,
SOURCEID,
EVENTCOUNT,
SECURITYFAILURE,
APPLICATIONFAILURE,
CONNECTIVITYFAILURE,
SUM(EVENTCOUNT) OVER() AS TOTALEVENTCOUNT
FROM
#SUMUSERANALYSIS AS u
WHERE
USERFLAG = 1
),
--Select top 5 exception events for current user
TopDataSet AS
(
SELECT
TOP(5)
id,
1 AS UserId,
description,
sourceId,
EventCount,
SecurityFailure,
ApplicationFailure,
ConnectivityFailure,
EventCount AS SumEventCount,
TotalEventCount,
0 AS UsersAffected
FROM
OrderedDataSet AS U
ORDER BY Id
),
-- Select information about same exceptions for other users
EachUserInfo AS
(
SELECT
f.ID,
UserStat.DESCRIPTION,
UserStat.SOURCEID,
UserStat.EVENTCOUNT,
UserStat.SECURITYFAILURE,
UserStat.APPLICATIONFAILURE,
UserStat.CONNECTIVITYFAILURE,
UserStat.USERID
FROM
#SUMUSERANALYSIS UserStat
JOIN TopDataSet AS f ON (f.SOURCEID = UserStat.SOURCEID AND UserStat.DESCRIPTION = f.DESCRIPTION)
),
OtherUsersInfo AS
(
SELECT
MAX(Id) AS Id,
2 AS UserId,
description,
sourceId,
AVG(EventCount * 1.0) AS EventCount,
AVG(SecurityFailure * 1.0) AS SecurityFailure,
AVG(ApplicationFailure * 1.0) AS ApplicationFailure,
AVG(ConnectivityFailure * 1.0) AS ConnectivityFailure,
0 AS SumEventCount,
0 AS TotalEventCount,
COUNT(DISTINCT COALESCE(userid,0)) AS UsersAffected
FROM
EachUserInfo
GROUP BY
sourceId,
description
),
-- Unify information about current user and all users
[Result] AS (
SELECT *
FROM
TopDataSet
UNION ALL
SELECT *
FROM
OtherUsersInfo
)
SELECT
r.Id,
r.UserId,
r.description,
s.Source,
r.EventCount,
r.SecurityFailure,
r.ApplicationFailure,
r.ConnectivityFailure,
r.SumEventCount,
r.TotalEventCount,
r.UsersAffected
FROM
[Result] r
JOIN apm.Source (NOLOCK) AS s ON s.SourceId = r.SourceId
ORDER BY
Id, UserId
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.SummaryPerformanceAnalysisReport'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.SummaryPerformanceAnalysisReport AS RETURN 1')
END
GO

/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: SummaryPerformanceAnalysisReport */
/* USED IN: Summary Performance Analysis Report */
/* INPUT PARAMETERS: */
/* @STARTDATE - Start date of the priod */
/* @ENDDATE - End date of the period */
/* @SOURCEIDS - List of source Id, separated by comma. Exp: '1,2,3' */
/* @MACHINEIDS - List of machine Id, separated by comma. Exp: '4,5,6' */
/* @INCLUDESUBNET - Subnet masks list, which should be included */
/* @EXCLUDESUBNET - Subnet mask list, which should be excluded */
/* @THRESHOLD - Event threshold */
/* @ORDERBY - Specifies field to which sorting should be applayed */
/* 1. Request Count (temporary obsolete) */
/* 2. Problems Count */
/* 3. Event Count */
/* 4. MAX Event Duration */
/* 5. AVG Event Duration */
/* 6. Event Size */
/************************************************************************************/
ALTER PROCEDURE APM.SummaryPerformanceAnalysisReport
@STARTDATE DATETIME,
@ENDDATE DATETIME,
@SOURCEIDS NVARCHAR(MAX),
@MACHINEIDS NVARCHAR(MAX),
@INCLUDESUBNET NVARCHAR(MAX),
@EXCLUDESUBNET NVARCHAR(MAX),
@THRESHOLD INT,
@PMSTATUS NVARCHAR(50),
@ORDERBY INT
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON

/****************************************************************************************/
/* ASSISTING TEMP TABLES */
/****************************************************************************************/

SELECT
@INCLUDESUBNET = REPLACE(@INCLUDESUBNET, N'*', N'%'),
@EXCLUDESUBNET = REPLACE(@EXCLUDESUBNET, N'*', N'%')

-- Filter table, which contains machine ids and source ids
-- typeid defines filter type - 1 for source and 2 for machine
-- valueId filter value - source id and machine id
CREATE TABLE #SOURCEMACHINEFILTERTABLE(
TYPEID INT,
VALUEID INT
)

-- Fill table #SOURCEMACHINEFILTERTABLE
INSERT
INTO #SOURCEMACHINEFILTERTABLE
SELECT
p.typeId AS TYPEID,
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@SOURCEIDS, @MACHINEIDS) AS p

-- Filter table for SubnetC values
CREATE TABLE #SUBNETCFILTERTABLE
(
IPID INT
)

-- Insert into filter id of the SubnetC to increase performence for event table
INSERT INTO #SUBNETCFILTERTABLE
SELECT DISTINCT
ipid
FROM
IP AS ip (NOLOCK)
JOIN APM.GetMultiParameters(CASE WHEN LEN(@INCLUDESUBNET) &gt; 0 THEN @INCLUDESUBNET ELSE N'%' END, N'') AS p1 ON (ip.SubnetC LIKE p1.Value)
LEFT OUTER JOIN APM.GetMultiParameters(CASE WHEN LEN(@EXCLUDESUBNET) &gt; 0 THEN @EXCLUDESUBNET ELSE N'Fake' END, N'') AS p2 ON (ip.SubnetC LIKE p2.Value)
WHERE
--Exclude subnets which have correspondance in @EXCLUDESUBNET parameter
p2.typeId IS NULL

-- Filter table, which contains PM Statuses of Events
CREATE TABLE #PMSTATUSFILTERTABLE(
VALUEID INT
)

-- Fill table #PMSTATUSFILTERTABLE
INSERT
INTO #PMSTATUSFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@PMSTATUS, N'') AS p

CREATE TABLE #CLIENTEVENT
(
CSEVENTID INT,
CSEVENTGROUPID INT,
EVENTCLASS NVARCHAR(50),
SOURCEID INT
)

INSERT INTO #CLIENTEVENT
SELECT
e.CSEVENTID,
e.CSEVENTGROUPID,
e.EVENTCLASS,
e.SOURCEID
FROM
APM.CSEvent (NOLOCK) AS e
JOIN #SOURCEMACHINEFILTERTABLE AS f1 ON (f1.VALUEID = e.SourceId AND f1.TYPEID = 1)
JOIN #SOURCEMACHINEFILTERTABLE AS f2 ON (f2.VALUEID = e.MachineId AND f2.TYPEID = 2)
JOIN #SUBNETCFILTERTABLE AS f3 ON e.ipid = f3.IPID
JOIN #PMSTATUSFILTERTABLE AS f4 ON (f4.VALUEID = e.PMStatus)
WHERE
e.ClassType = N'Performance'
AND e.UTCDate &gt;= @STARTDATE
AND e.UTCDate &lt; @ENDDATE

/****************************************************************************************************************/
/* MAIN QUERY */
/****************************************************************************************************************/
;WITH AJAXEvents AS
(
SELECT
E.CSEVENTID,
SUM(COALESCE(ajax.REQUESTSIZE, 0))+ SUM(COALESCE(ajax.ResponseSize, 0)) AS AjaxSize,
-- This field will be used only for Asynch Ajax, and for Asycnch Ajax CSAJAX table
-- contains only one row for each event, so sum doesn't make any difference
SUM(ajax.TotalTime) AS TotalTime
FROM
#CLIENTEVENT AS e
JOIN APM.CSAJAX AS ajax ON e.CSEVENTID = ajax.CSEventId
GROUP BY
e.CSEVENTID

),
CSEvents AS
(
SELECT
e.CSEVENTID,
e.CSEVENTGROUPID,
e.SOURCEID,
js.CSEventId AS JavaScriptEventId,
(CASE WHEN ((js.CSEventId IS NULL) AND (e.EVENTCLASS =N'CSMAMonitorLog')) THEN e.CSEVENTID ELSE NULL END) AS AsyncAjaxEventId,
(CASE WHEN ((js.CSEventId IS NULL) AND (e.EVENTCLASS =N'CSMPMonitorLog')) THEN e.CSEVENTID ELSE NULL END) AS PageEventId,
COALESCE(pe.TotalTime, COALESCE(js.TotalTime, ajax.TotalTime)) AS EventDuration,
COALESCE(pe.TotalSize, ajax.AjaxSize) AS EventSize
FROM
#CLIENTEVENT AS e
LEFT OUTER JOIN APM.CSJSCRIPTEVENT AS js (NOLOCK) ON js.CSEventId = e.CSEVENTID
LEFT OUTER JOIN AJAXEvents AS ajax (NOLOCK) ON ajax.CSEventId = e.CSEVENTID
LEFT OUTER JOIN APM.CSPAGEEVENT AS pe (NOLOCK) ON pe.CSEventId = e.CSEVENTID
),
SourceStat AS
(
SELECT
SourceId,
COUNT(JavaScriptEventId) AS JavaScriptEventCount,
COUNT(AsyncAjaxEventId) AS AsyncAjaxEventCount,
COUNT(PageEventId) AS PageEventCount,
COUNT(CSEventId) AS EventCount,
COUNT(DISTINCT CSEventGroupId) AS ProblemsCount,
MAX(EventDuration) AS MAXEventDuration,
AVG(EventDuration) AS AVGEventDuration,
AVG(EventSize) AS EventSize
FROM
CSEvents
WHERE
EventDuration / 1000.0 &gt;= @THRESHOLD
GROUP BY
SourceId
),
NumberedSources AS
(
SELECT
ROW_NUMBER() OVER(ORDER BY (CASE @ORDERBY
WHEN 2 THEN e.ProblemsCount
WHEN 3 THEN e.EventCount
WHEN 4 THEN e.MAXEventDuration
WHEN 5 THEN e.AVGEventDuration
WHEN 6 THEN e.EventSize
END) DESC) Id,
e.SourceId,
s.Source,
e.JavaScriptEventCount,
e.AsyncAjaxEventCount,
e.PageEventCount,
e.EventCount,
e.ProblemsCount,
e.MAXEventDuration/1000.0 AS MAXEventDuration,
e.AVGEventDuration/1000.0 AS AVGEventDuration,
-- Temporary obsolete field, return appropriate value, than it will be returned
1 AS requestCount,
e.EventSize/1024.0 AS EventSize,
SUM(e.EventCount) OVER() AS TotalEventCount
FROM
SourceStat AS e
JOIN APM.Source AS s (NOLOCK) ON e.SourceId = s.SourceId
)
SELECT TOP (10) *
FROM
NumberedSources
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.SummaryPerformanceAnalysisReportMaxScale'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.SummaryPerformanceAnalysisReportMaxScale AS RETURN 1')
END
GO

/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: SummaryPerformanceAnalysisReportMaxScale */
/* USED IN: Summary Performance Analysis Report */
/* INPUT PARAMETERS: */
/* @STARTDATE - Start date of the priod */
/* @ENDDATE - End date of the period */
/* @SOURCEIDS - List of source Id, separated by comma. Exp: '1,2,3' */
/* @MACHINEIDS - List of machine Id, separated by comma. Exp: '4,5,6' */
/* @INCLUDESUBNET - Subnet masks list, which should be included */
/* @EXCLUDESUBNET - Subnet mask list, which should be excluded */
/* @THRESHOLD - Event threshold */
/************************************************************************************/

ALTER PROCEDURE APM.SummaryPerformanceAnalysisReportMaxScale
@STARTDATE DATETIME,
@ENDDATE DATETIME,
@SOURCEIDS NVARCHAR(MAX),
@MACHINEIDS NVARCHAR(MAX),
@INCLUDESUBNET NVARCHAR(MAX),
@EXCLUDESUBNET NVARCHAR(MAX),
@PMSTATUS NVARCHAR(50),
@THRESHOLD INT
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON

/****************************************************************************************/
/* ASSISTING TEMP TABLES */
/****************************************************************************************/

-- Filter table, which contains machine ids and source ids
-- typeid defines filter type - 1 for source and 2 for machine
-- valueId filter value - source id and machine id
CREATE TABLE #SOURCEMACHINEFILTERTABLE(
TYPEID INT,
VALUEID INT
)

SELECT
@INCLUDESUBNET = REPLACE(@INCLUDESUBNET, N'*', N'%'),
@EXCLUDESUBNET = REPLACE(@EXCLUDESUBNET, N'*', N'%')


-- Fill table #SOURCEMACHINEFILTERTABLE
INSERT
INTO #SOURCEMACHINEFILTERTABLE
SELECT
p.typeId AS TYPEID,
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@SOURCEIDS, @MACHINEIDS) AS p

-- Filter table, which contains PM Statuses of Events
CREATE TABLE #PMSTATUSFILTERTABLE(
VALUEID INT
)

-- Fill table #PMSTATUSFILTERTABLE
INSERT
INTO #PMSTATUSFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@PMSTATUS, N'') AS p

-- Filter table for SubnetC values
CREATE TABLE #SUBNETCFILTERTABLE
(
IPID INT
)

-- Insert into filter id of the SubnetC to increase performence for event table
INSERT INTO #SUBNETCFILTERTABLE
SELECT DISTINCT
ipid
FROM
IP AS ip (NOLOCK)
JOIN APM.GetMultiParameters(CASE WHEN LEN(@INCLUDESUBNET) &gt; 0 THEN @INCLUDESUBNET ELSE N'%' END, N'') AS p1 ON (ip.SubnetC LIKE p1.Value)
LEFT OUTER JOIN APM.GetMultiParameters(CASE WHEN LEN(@EXCLUDESUBNET) &gt; 0 THEN @EXCLUDESUBNET ELSE N'Fake' END, N'') AS p2 ON (ip.SubnetC LIKE p2.Value)
WHERE
--Exclude subnets which have correspondance in @EXCLUDESUBNET parameter
p2.typeId IS NULL

CREATE TABLE #CLIENTEVENT
(
CSEVENTID INT,
CSEVENTGROUPID INT,
EVENTCLASS NVARCHAR(50) COLLATE database_default,
SOURCEID INT,
PAGEURI NVARCHAR(255) COLLATE database_default
)

INSERT INTO #CLIENTEVENT
SELECT
e.CSEVENTID,
e.CSEVENTGROUPID,
e.EVENTCLASS,
e.SOURCEID,
e.PAGEURI
FROM
APM.CSEvent (NOLOCK) AS e
JOIN #SOURCEMACHINEFILTERTABLE AS f1 ON (f1.VALUEID = e.SOURCEID AND f1.TYPEID = 1)
JOIN #SOURCEMACHINEFILTERTABLE AS f2 ON (f2.VALUEID = e.MACHINEID AND f2.TYPEID = 2)
JOIN #SUBNETCFILTERTABLE AS f3 ON e.IPID = f3.IPID
JOIN #PMSTATUSFILTERTABLE AS f4 ON (f4.VALUEID = e.PMSTATUS)
WHERE
e.CLASSTYPE = N'Performance'
AND e.PAGEURI IS NOT NULL
AND e.UTCDATE &gt;= @STARTDATE
AND e.UTCDATE &lt; @ENDDATE

;WITH JSAndAJAXEvent AS
(
SELECT
e.CSEVENTID,
e.SOURCEID,
e.PAGEURI,
COALESCE(js.TotalTime, ajax.TotalTime) AS EventDuration,
COALESCE(js.Action, ajax.Uri) AS Action
FROM
#CLIENTEVENT AS e
LEFT OUTER JOIN APM.CSJScriptEvent AS js (NOLOCK) ON js.CSEVENTID = e.CSEVENTID
LEFT OUTER JOIN APM.CSAJAX AS ajax (NOLOCK) ON ajax.CSEVENTID = e.CSEVENTID
WHERE
EVENTCLASS = N'CSMAMonitorLog'
AND COALESCE(js.TotalTime, ajax.TOTALTIME)/1000.0 &gt;= @THRESHOLD
),
-- As main query shows only top 10 sources,
-- this should be take into account for choosing max durations
SourceFilter AS
(
SELECT
ROW_NUMBER() OVER(ORDER BY COUNT(e.CSEVENTID) DESC) AS SourceRowNumber,
e.SOURCEID
FROM
#CLIENTEVENT AS e
GROUP BY
e.SOURCEID
),
JSAndAJAXEventsDuration AS
(
SELECT
ROW_NUMBER() OVER(PARTITION BY E.SourceId ORDER BY COUNT(e.CSEventId) DESC) AS Id,
e.SOURCEID,
e.PAGEURI,
e.Action,
COUNT(e.CSEVENTID) AS EventCount,
AVG(EventDuration) AS EventDuration
FROM
JSAndAJAXEvent AS e
JOIN SourceFilter AS s ON s.SOURCEID = e.SOURCEID
WHERE
s.SourceRowNumber &lt;= 10
GROUP BY
e.SOURCEID,
e.PAGEURI,
e.Action
),
PageEvent AS
(
SELECT ROW_NUMBER() OVER(PARTITION BY e.SOURCEID ORDER BY COUNT(e.CSEVENTID) DESC) AS Id,
e.SOURCEID,
COUNT(e.CSEVENTID) AS EventCount,
AVG(pe.TOTALTIME) AS EventDuration,
e.PAGEURI
FROM
#CLIENTEVENT AS e
JOIN APM.CSPAGEEVENT AS pe (NOLOCK) ON pe.CSEVENTID = e.CSEVENTID
JOIN SourceFilter AS s ON s.SOURCEID = e.SOURCEID
WHERE
pe.TOTALTIME/1000.0 &gt;=@THRESHOLD
AND s.SourceRowNumber &lt;= 10
GROUP BY
e.SOURCEID,
e.PAGEURI
)
SELECT
(
SELECT
COALESCE(MAX(EventDuration),0)/1000.0
FROM
PageEvent
WHERE
Id &lt;= 5
)AS MaxPageEventDuration,
(
SELECT
COALESCE(MAX(EventDuration),0)/1000.0
FROM
JSAndAJAXEventsDuration
WHERE
Id &lt;= 5
)AS MaxJSEventDuration
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.LoadTimeAnalysisBasedOnSubNet'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.LoadTimeAnalysisBasedOnSubNet AS RETURN 1')
END
GO

/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: LoadTimeAnalysisBasedOnSubNet */
/* USED IN: Load Time Analysis Based On Subnet as main data set query */
/* INPUT PARAMETERS: */
/* @STARTDATE - Start date of the priod */
/* @ENDDATE - End date of the period */
/* @SOURCEID - SourceId */
/* @MACHINEIDS - List of machine Id, separated by comma. Exp: '4,5,6' */
/* @INCLUDESUBNET - Subnet masks list, which should be included */
/* @EXCLUDESUBNET - Subnet mask list, which should be excluded */
/* @THRESHOLD - Event threshold */
/* @ORDERBY - Specifies field to which sorting should be applayed */
/* 1. Request Count (temporary obsolete) */
/* 2. Problems Count */
/* 4. Avg Event Duration */
/* 5. Latency */
/************************************************************************************/

ALTER PROCEDURE APM.LoadTimeAnalysisBasedOnSubNet
@STARTDATE DATETIME,
@ENDDATE DATETIME,
@SOURCEID NVARCHAR(MAX),
@MACHINEIDS NVARCHAR(MAX),
@INCLUDESUBNET NVARCHAR(MAX),
@EXCLUDESUBNET NVARCHAR(MAX),
@THRESHOLD INT,
@ORDERBY INT,
@PMSTATUS NVARCHAR(50)
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON

/****************************************************************************************/
/* ASSISTING TEMP TABLES */
/****************************************************************************************/

SELECT
@INCLUDESUBNET = REPLACE(@INCLUDESUBNET, N'*', N'%'),
@EXCLUDESUBNET = REPLACE(@EXCLUDESUBNET, N'*', N'%')

-- Filter table, which contains machine ids and source ids
-- valueId filter value - machine id
CREATE TABLE #MACHINEFILTERTABLE(
VALUEID INT
)

-- Fill table #SOURCEMACHINEFILTERTABLE
INSERT
INTO #MACHINEFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@MACHINEIDS, N'') AS p

-- Filter table, which contains PM Statuses of Events
CREATE TABLE #PMSTATUSFILTERTABLE(
VALUEID INT
)

-- Fill table #PMSTATUSFILTERTABLE
INSERT
INTO #PMSTATUSFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@PMSTATUS, N'') AS p

-- Filter table for SubnetC values
CREATE TABLE #SUBNETCFILTERTABLE
(
IPID INT,
SUBNETC NVARCHAR(50) COLLATE database_default
)

-- Insert into filter id of the SubnetC to increase performance for event table
INSERT INTO #SUBNETCFILTERTABLE
SELECT DISTINCT
IPID,
SUBNETC
FROM
APM.IP AS ip (NOLOCK)
JOIN APM.GetMultiParameters(CASE WHEN LEN(@INCLUDESUBNET) &gt; 0 THEN @INCLUDESUBNET ELSE N'%' END, N'') AS p1 ON (ip.SUBNETC LIKE p1.Value)
LEFT OUTER JOIN APM.GetMultiParameters(CASE WHEN LEN(@EXCLUDESUBNET) &gt; 0 THEN @EXCLUDESUBNET ELSE N'Fake' END, N'') AS p2 ON (ip.SUBNETC LIKE p2.Value)
WHERE
--Exclude subnets which have correspondance in @EXCLUDESUBNET parameter
p2.typeId IS NULL

CREATE TABLE #CLIENTEVENT
(
CSEVENTID INT,
CSEVENTGROUPID INT,
EVENTCLASS NVARCHAR(50) COLLATE database_default ,
SUBNETC NVARCHAR(50) COLLATE database_default
)

INSERT INTO #CLIENTEVENT
SELECT
e.CSEVENTID,
e.CSEVENTGROUPID,
e.EVENTCLASS,
f2.SUBNETC
FROM
APM.CSEvent (NOLOCK) AS e
JOIN #MACHINEFILTERTABLE AS f ON (f.VALUEID = e.MACHINEID)
JOIN #SUBNETCFILTERTABLE AS f2 ON e.IPID = f2.IPID
JOIN #PMSTATUSFILTERTABLE AS f3 ON (f3.VALUEID = e.PMSTATUS)
WHERE
e.CLASSTYPE = N'Performance'
AND e.PAGEURI IS NOT NULL
AND e.SOURCEID = @SOURCEID
AND e.UTCDATE &gt;= @STARTDATE
AND e.UTCDATE &lt; @ENDDATE

/****************************************************************************************/
/* MAIN QUERY */
/****************************************************************************************/
;WITH AJAXEvent AS
(
SELECT
e.CSEVENTID,
e.SUBNETC,
ajax.Synchronous,
SUM(ajax.NetworkTime) AS NetworkTime,
SUM(ajax.ServerTime) AS ServerTime,
SUM(ajax.ResponseTime) AS ResponseTime,
AVG(ajax.Latency) AS Latency,
SUM(ajax.TotalTime) AS TotalTime
FROM
#CLIENTEVENT AS e
JOIN APM.CSAJAX AS ajax (NOLOCK) ON ajax.CSEventId = e.CSEVENTID
GROUP BY
e.CSEVENTID,
e.SUBNETC,
ajax.Synchronous

),
ClientEvents AS
(
SELECT
e.SUBNETC,
e.CSEVENTID,
e.CSEVENTGROUPID,
-- if JScript table has corresponding row (not null value), than consider it is java script event
js.CSEventId AS JavaScriptEventId,
-- If it is not JavaScript event, then define its type by event class type
(CASE WHEN ((js.CSEventId IS NULL) AND (e.EVENTCLASS =N'CSMAMonitorLog')) THEN e.CSEVENTID ELSE NULL END) AS AsyncAjaxEventId,
(CASE WHEN ((js.CSEventId IS NULL) AND (e.EVENTCLASS =N'CSMPMonitorLog')) THEN e.CSEVENTID ELSE NULL END) AS PageEventId,
-- Define duration by joined table. As Page Event, Asynch Ajax and Java script
-- events are mutually exclusive it can be done as folllows
COALESCE(p.TotalTime, COALESCE(js.TotalTime, ajax.TotalTime)) AS EventDuration,
p.NetworkTime AS PageLoadNetworkTime,
p.ServerTime AS PageLoadServerTime,
p.DOMTime AS PageDOMLoad,
p.PeripheralTime AS PagePeripheralTime,
p.OnLoadTime AS PageOnLoadTime,
p.TotalTime AS PageEventTime,
(ajax.NetworkTime + ajax.ResponseTime) AS AjaxNetworkTime,
ajax.ServerTime AS AjaxServerTime,
-- If event is asynch ajax, then there is no corresponding row in JavaScript table,
-- If it is synch ajax, then its total duration should be taken from java script total time
COALESCE(js.TotalTime, ajax.TotalTime) AS AjaxTotalTime,
-- Client time should be calculated as total time, minus network, server and response time,
-- But total time should be taken not from ajax table, it is depend on event type
COALESCE(js.TotalTime, ajax.TotalTime)
-- For AJAX event ther could by no corresponding row in AJAX table, then all time consider to be Client
- COALESCE(ajax.NetworkTime + ajax.ResponseTime + ajax.ServerTime, 0) AS AjaxClientTime,
--Latency belongs either to page event or to Ajax event
COALESCE(p.Latency, ajax.Latency) AS Latency,
COUNT(e.CSEVENTID) OVER() AS TotalEventCount
FROM
#CLIENTEVENT AS e
LEFT OUTER JOIN AJAXEvent AS ajax ON ajax.CSEventId = e.CSEVENTID
LEFT OUTER JOIN APM.CSPageEvent AS p (NOLOCK) ON P.CSEventId = e.CSEVENTID
LEFT OUTER JOIN APM.CSJScriptEvent AS js (NOLOCK) ON js.CSEventId = e.CSEVENTID
WHERE
COALESCE(p.TotalTime, COALESCE(js.TotalTime, ajax.TotalTime)) / 1000.0 &gt;= @THRESHOLD
),
-- Aggregate data for each subnet
SubnetSummary AS
(
SELECT
SubnetC,
COUNT(CSEventId) AS EventCount,
COUNT(DISTINCT CSEventGroupId) AS ProblemCount,
-- For counting events by types, use that COUNT does not calculates null values
COUNT(JavaScriptEventId) AS JSEventCount,
COUNT(AsyncAjaxEventId) AS AsynchAjaxEvent,
COUNT(PageEventId) AS PageEventCount,
AVG(PageLoadNetworkTime)/1000.0 AS PageLoadNetworkTime,
AVG(PageLoadServerTime)/1000.0 AS PageLoadServerTime,
AVG(PageDOMLoad)/1000.0 AS PageDOMLoad,
AVG(PagePeripheralTime)/1000.0 AS PagePeripheralTime,
AVG(PageOnLoadTime)/1000.0 AS PageOnLoadTime,
AVG(Latency) AS Latency,
AVG(AjaxNetworkTime)/1000.0 AS AjaxNetworkTime,
AVG(AjaxServerTime)/1000.0 AS AjaxServerTime,
AVG(AjaxClientTime)/1000.0 AS ClientTime,
AVG(EventDuration)/1000.0 AS AvgEventDuration,
-- This aggregation has no difference as it is same for all rows
MAX(TotalEventCount) AS TotalEventCount
FROM
ClientEvents
GROUP BY
SubnetC
)
SELECT TOP(20)
row_number() OVER(ORDER BY (CASE @ORDERBY
WHEN 1 THEN ProblemCount
WHEN 2 THEN EventCount
WHEN 3 THEN coalesce(PageLoadServerTime, 0) + coalesce(AjaxServerTime, 0)
WHEN 4 THEN AvgEventDuration
WHEN 5 THEN Latency
END) DESC) Id,
SubnetC,
EventCount,
ProblemCount,
PageEventCount,
JSEventCount,
AsynchAjaxEvent,
PageLoadNetworkTime,
PageLoadServerTime,
PageDOMLoad,
PagePeripheralTime,
PageOnLoadTime,
AjaxNetworkTime,
AjaxServerTime,
ClientTime,
Latency,
AvgEventDuration,
TotalEventCount
FROM
SubnetSummary
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.LoadTimeAnalysisBasedOnSubNetMaxScale'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.LoadTimeAnalysisBasedOnSubNetMaxScale AS RETURN 1')
END
GO

/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: LoadTimeAnalysisBasedOnSubNet */
/* USED IN: Load Time Analysis Based On Subnet for calculating max value in */
/* subreports, to make one scaling for all sub reports */
/* INPUT PARAMETERS: */
/* @STARTDATE - Start date of the priod */
/* @ENDDATE - End date of the period */
/* @SOURCEID - SourceId */
/* @MACHINEIDS - List of machine Id, separated by comma. Exp: '4,5,6' */
/* @INCLUDESUBNET - Subnet masks list, which should be included */
/* @EXCLUDESUBNET - Subnet mask list, which should be excluded */
/************************************************************************************/
alter PROCEDURE APM.LoadTimeAnalysisBasedOnSubNetMaxScale
@STARTDATE DATETIME,
@ENDDATE DATETIME,
@SOURCEID NVARCHAR(MAX),
@MACHINEIDS NVARCHAR(MAX),
@INCLUDESUBNET NVARCHAR(MAX),
@EXCLUDESUBNET NVARCHAR(MAX),
@PMSTATUS NVARCHAR(50)
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON
/****************************************************************************************/
/* ASSISTING TEMP TABLES */
/****************************************************************************************/

SELECT
@INCLUDESUBNET = REPLACE(@INCLUDESUBNET, N'*', N'%'),
@EXCLUDESUBNET = REPLACE(@EXCLUDESUBNET, N'*', N'%')

-- Filter table, which contains machine ids and source ids
-- valueId filter value - machine id
CREATE TABLE #MACHINEFILTERTABLE(
VALUEID INT
)

-- Fill table #SOURCEMACHINEFILTERTABLE
INSERT
INTO #MACHINEFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@MACHINEIDS, N'') AS p

-- Filter table, which contains PM Statuses of Events
CREATE TABLE #PMSTATUSFILTERTABLE(
VALUEID INT
)

-- Fill table #PMSTATUSFILTERTABLE
INSERT
INTO #PMSTATUSFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@PMSTATUS, N'') AS p

CREATE TABLE #IPFILTER
(
IPID INT
)

INSERT INTO #IPFILTER
SELECT DISTINCT
ipid
FROM
apm.IP AS ip (NOLOCK)
JOIN APM.GetMultiParameters(CASE WHEN LEN(@INCLUDESUBNET) &gt; 0 THEN @INCLUDESUBNET ELSE N'%' END, N'') AS p1 ON (ip.SubnetC LIKE p1.Value)
LEFT OUTER JOIN APM.GetMultiParameters(CASE WHEN LEN(@EXCLUDESUBNET) &gt; 0 THEN @EXCLUDESUBNET ELSE N'Fake' END, N'') AS p2 ON (ip.SubnetC LIKE p2.Value)
WHERE
--Exclude subnets which have correspondance in @EXCLUDESUBNET parameter
p2.typeId IS NULL

CREATE TABLE #CLIENTEVENT
(
CSEVENTID INT,
EVENTCLASS NVARCHAR(50) COLLATE database_default,
PAGEURI NVARCHAR(255) COLLATE database_default,
SUBNETC NVARCHAR(50) COLLATE database_default
)

INSERT INTO #CLIENTEVENT
SELECT
e.CSEVENTID,
e.EVENTCLASS,
e.PAGEURI,
ip.SUBNETC
FROM
-- Max values should be selected not only for appropriate subnetc, but for all
-- (as in subreports, relative values to other is shown). So filtering by subnets could not be hold here
APM.CSEvent (NOLOCK) AS e
JOIN #MACHINEFILTERTABLE AS f ON (f.VALUEID = e.MACHINEID)
JOIN #IPFILTER AS f2 ON (e.IPID = f2.IPID)
JOIN #PMSTATUSFILTERTABLE AS f3 ON (f3.VALUEID = e.PMSTATUS)
JOIN APM.IP AS ip (NOLOCK) ON ip.IPID = e.IPID

WHERE
e.CLASSTYPE = N'Performance'
AND e.PAGEURI IS NOT NULL
AND e.SOURCEID = @SOURCEID
AND e.UTCDATE &gt;= @STARTDATE
AND e.UTCDATE &lt; @ENDDATE

-- Filter table for SubnetC values
CREATE TABLE #SUBNETCFILTERTABLE
(
SUBNETC NVARCHAR(50) COLLATE database_default
)

-- In report shown only top 20 subnets by event count
-- Besides, user specifies filter by subnet, so select subnets, for which MAX should be selected
INSERT INTO #SUBNETCFILTERTABLE
SELECT
TOP(20)
e.SUBNETC
FROM
#CLIENTEVENT AS e
GROUP BY
e.SUBNETC
ORDER BY
COUNT(e.CSEVENTID) DESC


/****************************************************************************************/
/* MAIN QUERIES */
/****************************************************************************************/
;WITH AJAXEvents AS
(
SELECT
e.CSEVENTID,
-- This field need only for asynch ajax events, and for this type here can by only one row,
-- so aggregation doesn't matter
MAX(ajax.URI) AS AjaxAction,
SUM(ajax.TOTALTIME) AS TotalTime
FROM
#CLIENTEVENT AS e
JOIN APM.CSAJAX AS ajax (NOLOCK) ON ajax.CSEVENTID = e.CSEVENTID
WHERE
e.EVENTCLASS = N'CSMAMonitorLog' OR e.EVENTCLASS = N'CSMSMonitorLog'
GROUP BY
e.CSEVENTID
),
JSEvents AS
(
SELECT
e.CSEVENTID,
e.SUBNETC,
e.PAGEURI,
COALESCE(js.ACTION, ajax.AjaxAction) AS Action,
COALESCE(js.TOTALTIME, ajax.TotalTime) AS EventDuration,
--Calculate average event duration for all subnets
AVG(COALESCE(js.TOTALTIME, ajax.TotalTime)) OVER(PARTITION BY e.PAGEURI,
COALESCE(js.Action, ajax.AjaxAction)) AS CommonDuration
FROM
#CLIENTEVENT AS e
LEFT OUTER JOIN APM.CSJScriptEvent AS js (NOLOCK) ON js.CSEVENTID = e.CSEVENTID
LEFT OUTER JOIN AJAXEvents AS ajax ON ajax.CSEVENTID = e.CSEVENTID
WHERE
e.EVENTCLASS = N'CSMAMonitorLog' OR e.EVENTCLASS = N'CSMSMonitorLog'
),
JSActionsForSubnets AS
(
SELECT
ROW_NUMBER() OVER(PARTITION BY js.SUBNETC ORDER BY COUNT(CSEVENTID) DESC) AS Id,
COUNT(CSEVENTID) AS EventCount,
js.SUBNETC,
Action,
PAGEURI,
MAX(CommonDuration) AS CommonDuration,
AVG(EventDuration) AS AvgActionDuration
FROM
JSEvents AS js
JOIN #SUBNETCFILTERTABLE AS f ON f.SUBNETC = js.SUBNETC
GROUP BY
js.SUBNETC,
PageUri,
Action
),
PageEvents AS
(
SELECT
e.CSEVENTID,
e.PAGEURI,
e.SUBNETC,
p.TOTALTIME,
--Calculate Average page load duration for all subnets
AVG(p.TOTALTIME) OVER(PARTITION BY e.PAGEURI) AS PageAvgDuration
FROM
#CLIENTEVENT AS e
JOIN APM.CSPageEvent AS p (NOLOCK) ON e.CSEVENTID = p.CSEVENTID
),
PageEventsForSubNets AS
(
SELECT
ROW_NUMBER() OVER(PARTITION BY e.SUBNETC ORDER BY COUNT(e.CSEVENTID) DESC) AS Id,
e.SUBNETC,
e.PAGEURI,
AVG(e.TOTALTIME) AS PageAvgSubNetDuration,
MAX(e.PageAvgDuration) AS PageAvgDuration
FROM
PageEvents AS e
JOIN #SUBNETCFILTERTABLE AS f ON f.SUBNETC = e.SUBNETC
GROUP BY
e.SUBNETC,
e.PAGEURI
)
SELECT
(SELECT COALESCE(MAX(CASE WHEN CommonDuration &gt;= AvgActionDuration THEN CommonDuration ELSE AvgActionDuration END)/1000.0, 0)
FROM
JSActionsForSubnets
WHERE Id &lt;= 5) AS MaxAjaxDuration,
(SELECT COALESCE(MAX(CASE WHEN PageAvgDuration &gt;= PageAvgSubNetDuration THEN PageAvgDuration ELSE PageAvgSubNetDuration END)/1000.0, 0)
FROM
PageEventsForSubNets
WHERE Id &lt;= 5) AS MaxPageLoadDuration
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.LoadTimeAnalysisBasedOnSubNetTopJSAndAJAXCalls'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.LoadTimeAnalysisBasedOnSubNetTopJSAndAJAXCalls AS RETURN 1')
END
GO

/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: LoadTimeAnalysisBasedOnSubNetTopJSAndAJAXCalls */
/* USED IN: Load Time Analysis Based On Subnet for Top JS ajax calls subreport */
/* INPUT PARAMETERS: */
/* @STARTDATE - Start date of the priod */
/* @ENDDATE - End date of the period */
/* @SOURCEID - SourceId */
/* @MACHINEIDS - List of machine Id, separated by comma. Exp: '4,5,6' */
/* @SUBNETC - SubnetC for which data should be selected */
/* @THRESHOLD - Event threshold */
/************************************************************************************/
alter PROCEDURE APM.LoadTimeAnalysisBasedOnSubNetTopJSAndAJAXCalls
@STARTDATE DATETIME,
@ENDDATE DATETIME,
@SOURCEID NVARCHAR(MAX),
@MACHINEIDS NVARCHAR(MAX),
@SUBNETC NVARCHAR(25),
@THRESHOLD INT,
@PMSTATUS NVARCHAR(50)
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON

/****************************************************************************************/
/* ASSISTING TEMP TABLES */
/****************************************************************************************/

-- Filter table, which contains machine ids and source ids
-- valueId filter value - machine id
CREATE TABLE #MACHINEFILTERTABLE(
VALUEID INT
)

-- Fill table #SOURCEMACHINEFILTERTABLE
INSERT
INTO #MACHINEFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@MACHINEIDS, N'') AS p

-- Filter table, which contains PM Statuses of Events
CREATE TABLE #PMSTATUSFILTERTABLE(
VALUEID INT
)

-- Fill table #PMSTATUSFILTERTABLE
INSERT
INTO #PMSTATUSFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@PMSTATUS, N'') AS p

CREATE TABLE #CLIENTEVENTFORALLSUBNETS
(
CSEVENTID INT,
PAGEURI NVARCHAR(255) collate database_default,
SUBNETC NVARCHAR(50) collate database_default
)

-- Filter Event Table by incoming parameters
-- Filtering by SubnetC is not made here, as relative time information
-- for all other sources should be also calculated
INSERT INTO #CLIENTEVENTFORALLSUBNETS
SELECT
e.CSEventId,
e.PageUri,
ip.SubNetC
FROM
APM.CSEvent (NOLOCK) AS e
JOIN #MACHINEFILTERTABLE AS f ON (f.VALUEID = e.MachineId)
JOIN #PMSTATUSFILTERTABLE AS f1 ON (f1.VALUEID = e.PMStatus)
JOIN APM.IP (NOLOCK) ON ip.ipid = e.ipid
WHERE
e.SourceId = @SOURCEID
--Select only Asynch AJAX and JS events
AND (e.EventClass = N'CSMAMonitorLog' OR e.EventClass = N'CSMSMonitorLog')
AND e.UTCDate &gt;= @STARTDATE
AND e.UTCDate &lt; @ENDDATE
AND PageUri IS NOT NULL

-- Events should be selected only for that pages, which are actual for specified @SUBNETC
-- If for the @SUBNETC there is no one event for some page, events for this page should not be selected at all
CREATE TABLE #CLIENTEVENTFILTEREDBYPAGEURI
(
CSEVENTID INT,
PAGEURI NVARCHAR(255) COLLATE database_default,
SUBNETC NVARCHAR(50) COLLATE database_default
)

INSERT INTO #CLIENTEVENTFILTEREDBYPAGEURI
SELECT
e.CSEVENTID,
e.PAGEURI,
e.SUBNETC
FROM
#CLIENTEVENTFORALLSUBNETS AS e
WHERE
e.SUBNETC = @SUBNETC
AND e.PAGEURI IN (SELECT
e1.PAGEURI
FROM
#CLIENTEVENTFORALLSUBNETS AS e1
WHERE
e1.SUBNETC = @SUBNETC
)

/********************************************************************************************************/
/* MAIN QUERY */
/********************************************************************************************************/
;WITH AJAXEvents AS
(
SELECT
e.CSEVENTID,
e.PAGEURI,
e.SUBNETC,
-- This field need only for asynch ajax events, and for this type here can by only one row,
-- so aggregation doesn't matter
MAX(ajax.Uri) AS AjaxAction,
SUM(ajax.ServerTime) AS ServerTime,
SUM(ajax.NetworkTime + ajax.ResponseTime) AS NetworkTime,
SUM(ajax.TotalTime) AS TotalTime,
SUM(COALESCE(ajax.REQUESTSIZE, 0) + COALESCE(ajax.ResponseSize, 0)) AS CallSize
FROM
#CLIENTEVENTFILTEREDBYPAGEURI AS e
JOIN APM.CSAJAX AS ajax (NOLOCK) ON e.CSEVENTID = ajax.CSEventId
GROUP BY
e.CSEVENTID,
e.PAGEURI,
e.SUBNETC
),
CSJSEvents AS
(
SELECT
e.PAGEURI,
e.SUBNETC,
e.CSEVENTID,
COALESCE(js.Action, ajax.AjaxAction) AS AjaxAction,
COALESCE(js.TotalTime, ajax.TotalTime)/1000.0 AS TotalTime,
COALESCE(ajax.NetworkTime, 0)/1000.0 AS NetworkTime,
COALESCE(ajax.ServerTime, 0)/1000.0 AS ServerTime,
-- don't change size to 0, as average size should be calculated only for ajax calls, not all events
ajax.CallSize/1024.0 AS CallSize
FROM
#CLIENTEVENTFILTEREDBYPAGEURI AS e
LEFT OUTER JOIN APM.CSJScriptEvent AS js (NOLOCK) ON js.CSEventid = e.CSEVENTID
LEFT OUTER JOIN AJAXEvents AS ajax (NOLOCK) ON ajax.CSEventid = e.CSEVENTID
WHERE
-- Threshold condition should be applied only for Asynch Ajax Events,
-- For Synch Ajax this condition is applied to JS event
COALESCE(js.TotalTime, ajax.TotalTime)/1000.0 &gt;= @THRESHOLD
),
AJAXActionInfo AS
(
SELECT
PageUri,
AjaxAction,
COUNT(CASE WHEN Subnetc = @SUBNETC THEN CSEventId END) AS EventCount,
AVG(CASE WHEN Subnetc = @SUBNETC THEN NetworkTime END) AS NetworkTime,
AVG(CASE WHEN Subnetc = @SUBNETC THEN ServerTime END) AS ServerTime,
AVG(CASE WHEN Subnetc = @SUBNETC THEN TotalTime - (NetworkTime + ServerTime) END) AS ClientTime,
AVG(CASE WHEN Subnetc = @SUBNETC THEN TotalTime END) AS TotalTime,
AVG(CASE WHEN Subnetc = @SUBNETC THEN CallSize END) AS AJAXCallSize,
AVG(NetworkTime) AS CommonNetworkTime,
AVG(ServerTime) AS CommonServerTime,
AVG(TotalTime - (NetworkTime + ServerTime)) AS CommonClientTime,
AVG(TotalTime) AS CommonTotalTime
FROM
CSJSEvents
GROUP BY
PageUri,
AjaxAction
),
OrderedActions AS
(
SELECT
ROW_NUMBER() OVER(ORDER BY EventCount DESC) AS id,
EventCount,
AjaxAction,
pageUri,
ClientTime,
NetworkTime,
ServerTime,
TotalTime,
CommonClientTime,
CommonNetworkTime,
CommonServerTime,
CommonTotalTime,
AJAXCallSize,
SUM(EventCount) OVER() AS TotalEvents
FROM
AJAXActionInfo
)
--Second row is used to show relative AJAX execution time for other subnets
SELECT
d.id,
rowId.n AS rowId,
d.pageUri,
d.AjaxAction,
(CASE WHEN rowId.n = 1 THEN d.EventCount ELSE 0 END )AS EventCount,
(CASE WHEN rowId.n = 1 THEN d.ClientTime ELSE d.CommonClientTime END )AS ClientTime,
(CASE WHEN rowId.n = 1 THEN d.NetworkTime ELSE d.CommonNetworkTime END )AS NetworkTime,
(CASE WHEN rowId.n = 1 THEN d.ServerTime ELSE d.CommonServerTime END )AS ServerTime,
(CASE WHEN rowId.n = 1 THEN d.TotalTime ELSE d.CommonTotalTime END) AS TotalTime,
(CASE WHEN rowId.n = 1 THEN d.AJAXCallSize ELSE 0 END )AS AJAXCallSize,
(CASE WHEN rowId.n = 1 THEN d.TotalEvents ELSE 0 END )AS TotalEvents
FROM
APM.fn_nums(2) AS rowId,
OrderedActions AS d
WHERE
d.id &lt;= 5
ORDER BY
id,
rowId
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.LoadTimeAnalysisBasedOnSubNetTopPages'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.LoadTimeAnalysisBasedOnSubNetTopPages AS RETURN 1')
END
GO

/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: LoadTimeAnalysisBasedOnSubNetTopPages */
/* USED IN: Load Time Analysis Based On Subnet for Top pages subreport */
/* INPUT PARAMETERS: */
/* @STARTDATE - Start date of the priod */
/* @ENDDATE - End date of the period */
/* @SOURCEID - SourceId */
/* @MACHINEIDS - List of machine Id, separated by comma. Exp: '4,5,6' */
/* @SUBNETC - SubnetC for which data should be selected */
/* @THRESHOLD - Event threshold */
/************************************************************************************/
ALTER PROCEDURE APM.LoadTimeAnalysisBasedOnSubNetTopPages
@STARTDATE DATETIME,
@ENDDATE DATETIME,
@SOURCEID NVARCHAR(MAX),
@MACHINEIDS NVARCHAR(MAX),
@SUBNETC NVARCHAR(25),
@THRESHOLD INT,
@PMSTATUS NVARCHAR(50)
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON

/****************************************************************************************/
/* ASSISTING TEMP TABLES */
/****************************************************************************************/

-- Filter table, which contains machine ids and source ids
-- valueId filter value - machine id
CREATE TABLE #MACHINEFILTERTABLE(
VALUEID INT
)

-- Fill table #SOURCEMACHINEFILTERTABLE
INSERT
INTO #MACHINEFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@MACHINEIDS, N'') AS p

-- Filter table, which contains PM Statuses of Events
CREATE TABLE #PMSTATUSFILTERTABLE(
VALUEID INT
)

-- Fill table #PMSTATUSFILTERTABLE
INSERT
INTO #PMSTATUSFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@PMSTATUS, N'') AS p

CREATE TABLE #CLIENTEVENTFORALLSUBNETS
(
CSEVENTID INT,
PAGEURI NVARCHAR(255) COLLATE database_default,
SUBNETC NVARCHAR(50) COLLATE database_default
)

-- Filter Event Table by incoming parameters
-- Filtering by SubnetC is not made here, as relative time information
-- for all other sources should be also calculated
INSERT INTO #CLIENTEVENTFORALLSUBNETS
SELECT
e.CSEventId,
e.PageUri,
ip.SubNetC
FROM
APM.CSEvent (NOLOCK) AS e
JOIN #MACHINEFILTERTABLE AS f ON (f.VALUEID = e.MachineId)
JOIN #PMSTATUSFILTERTABLE AS f1 ON (f1.VALUEID = e.PMStatus)
JOIN APM.IP (NOLOCK) ON ip.ipid = e.ipid
WHERE
e.SourceId = @SOURCEID
AND e.EventClass = N'CSMPMonitorLog'
AND e.UTCDate &gt;= @STARTDATE
AND e.UTCDate &lt; @ENDDATE
AND PageUri IS NOT NULL

-- Events should be selected only for that pages, which are actual for specified @SUBNETC
-- If for the @SUBNETC there is no one event for some page, events for this page should not be selected at all
;WITH CSPageEvents AS
(
SELECT
e.CSEVENTID,
e.PAGEURI,
pe.NetworkTime,
pe.ServerTime,
pe.DOMTime,
pe.PeripheralTime,
pe.OnLoadTime,
pe.TotalTime,
pe.TotalSize,
e.SUBNETC
FROM
#CLIENTEVENTFORALLSUBNETS (NOLOCK) AS e
JOIN APM.CSPageEvent AS pe ON pe.cseventid = e.CSEVENTID
WHERE
e.PAGEURI IN (SELECT DISTINCT
e1.PAGEURI
FROM
#CLIENTEVENTFORALLSUBNETS AS e1
WHERE
e1.SUBNETC = @SUBNETC
)
AND pe.TotalTime/1000.0 &gt; @THRESHOLD
),
PageProcessingTime AS
(
SELECT
PageUri,
COUNT(CASE WHEN Subnetc = @SUBNETC THEN CSEVENTID END) AS EventCount,
AVG(CASE WHEN Subnetc = @SUBNETC THEN COALESCE(NetworkTime, 0) END)/1000 AS NetworkTime,
AVG(CASE WHEN Subnetc = @SUBNETC THEN COALESCE(ServerTime, 0) END)/1000 AS ServerTime,
AVG(CASE WHEN Subnetc = @SUBNETC THEN COALESCE(DOMTime, 0) END)/1000 AS DOMTime,
AVG(CASE WHEN Subnetc = @SUBNETC THEN COALESCE(PeripheralTime, 0) END)/1000 AS PeripheralTime,
AVG(CASE WHEN Subnetc = @SUBNETC THEN COALESCE(OnLoadTime, 0) END)/1000 AS OnLoadTime,
AVG(CASE WHEN Subnetc = @SUBNETC THEN COALESCE(TotalTime, 0) END)/1000 AS TotalTime,
AVG(CASE WHEN Subnetc = @SUBNETC THEN COALESCE(TotalSize, 0) END)/1024.0 AS TotalSize,
AVG(NetworkTime)/1000 AS CommonNetworkTime,
AVG(ServerTime)/1000 AS CommonServerTime,
AVG(DOMTime)/1000 AS CommonDOMTime,
AVG(PeripheralTime)/1000 AS CommonPeripheralTime,
AVG(OnLoadTime)/1000 AS CommonOnLoadTime,
AVG(TotalTime)/1000 AS CommonTotalTime
FROM
CSPageEvents
GROUP BY
PageUri
),
NumberedPages AS
(
SELECT
row_number() OVER(ORDER BY EventCount DESC) AS id,
PageUri,
EventCount,
NetworkTime,
ServerTime,
DOMTime,
PeripheralTime,
OnLoadTime,
TotalTime,
TotalSize,
CommonNetworkTime,
CommonServerTime,
CommonDOMTime,
CommonPeripheralTime,
CommonOnLoadTime,
CommonTotalTime,
SUM(EventCount) OVER() AS TotalEvents
FROM
PageProcessingTime
),
OneRowData AS
(
SELECT
TOP(5)
id,
PageUri,
EventCount,
NetworkTime,
ServerTime,
DOMTime,
PeripheralTime,
OnLoadTime,
TotalTime,
TotalSize,
CommonNetworkTime,
CommonServerTime,
CommonDOMTime,
CommonPeripheralTime,
CommonOnLoadTime,
(COALESCE(CommonNetworkTime, 0) + COALESCE(CommonServerTime, 0)+ COALESCE(CommonDOMTime, 0) + COALESCE(CommonPeripheralTime, 0) + COALESCE(CommonOnLoadTime, 0)) AS CommonTotalTime,
TotalEvents
FROM
NumberedPages
WHERE
EventCount &gt; 0
ORDER BY id
)
--Second row is used to show relative Page Load time for other subnets
SELECT
d.id,
rowId.n AS rowId,
d.PageUri,
(CASE WHEN rowId.n = 1 THEN d.EventCount ELSE 0 END )AS EventCount,
(CASE WHEN rowId.n = 1 THEN d.NetworkTime ELSE d.CommonNetworkTime END )AS NetworkTime,
(CASE WHEN rowId.n = 1 THEN d.ServerTime ELSE d.CommonServerTime END )AS ServerTime,
(CASE WHEN rowId.n = 1 THEN d.DOMTime ELSE d.CommonDOMTime END )AS DOMTime,
(CASE WHEN rowId.n = 1 THEN d.PeripheralTime ELSE d.CommonPeripheralTime END )AS PeripheralTime,
(CASE WHEN rowId.n = 1 THEN d.OnLoadTime ELSE d.CommonOnLoadTime END )AS OnLoadTime,
(CASE WHEN rowId.n = 1 THEN d.TotalTime ELSE d.CommonTotalTime END )AS TotalTime,
(CASE WHEN rowId.n = 1 THEN d.TotalSize ELSE d.TotalSize END )AS TotalSize,
(CASE WHEN rowId.n = 1 THEN d.TotalEvents ELSE d.TotalEvents END )AS TotalEvents,
--Get ajax call flag
CASE WHEN EXISTS(
SELECT *
FROM #CLIENTEVENTFORALLSUBNETS c
JOIN APM.CSAJAX AS csaj (NOLOCK) ON csaj.cseventid = c.CSEVENTID
WHERE d.PageUri = c.PAGEURI
) THEN '*' ELSE ''
END AS Extension
FROM
APM.fn_nums(2) AS rowId,
OneRowData AS d
ORDER BY
id,
rowId
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.ClientLatencyDistributionBySources'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.ClientLatencyDistributionBySources AS RETURN 1')
END
GO

/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME:ClientLatencyDistributionBySources */
/* USED IN: Client Latency Distribution for summary table by sources */
/* INPUT PARAMETERS: */
/* @STARTDATE - Start date of the priod */
/* @ENDDATE - End date of the period */
/* @SOURCEIDS - List of source Id, separated by comma. Exp: '1,2,3' */
/* @MACHINEIDS - List of machine Id, separated by comma. Exp: '4,5,6' */
/* @SUBNETC - List subnet type C, selected by user */
/* @ORDERBY - Specifies latency range to which ordering should be applied */
/************************************************************************************/

ALTER PROCEDURE APM.ClientLatencyDistributionBySources
@STARTDATE DATETIME,
@ENDDATE DATETIME,
@SOURCEIDS NVARCHAR(MAX),
@MACHINEIDS NVARCHAR(MAX),
@INCLUDESUBNET NVARCHAR(MAX),
@EXCLUDESUBNET NVARCHAR(MAX),
@PMSTATUS NVARCHAR(50),
@ORDERBY INT
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON

/****************************************************************************************/
/* ASSISTING TEMP TABLES */
/****************************************************************************************/
SELECT
@INCLUDESUBNET = REPLACE(@INCLUDESUBNET, N'*', N'%'),
@EXCLUDESUBNET = REPLACE(@EXCLUDESUBNET, N'*', N'%')

-- Filter table, which contains machine ids and source ids
-- typeid defines filter type - 1 for source and 2 for machine
-- valueId filter value - source id and machine id
CREATE TABLE #SOURCEMACHINEFILTERTABLE(
TYPEID INT,
VALUEID INT
)

-- Fill table #SOURCEMACHINEFILTERTABLE
INSERT
INTO #SOURCEMACHINEFILTERTABLE
SELECT
p.typeId AS TYPEID,
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@SOURCEIDS, @MACHINEIDS) AS p


-- Filter table, which contains PM Statuses of Events
CREATE TABLE #PMSTATUSFILTERTABLE(
VALUEID INT
)

-- Fill table #PMSTATUSFILTERTABLE
INSERT
INTO #PMSTATUSFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@PMSTATUS, N'') AS p

-- Filter table for SubnetC values
CREATE TABLE #SUBNETCFILTERTABLE
(
IPID INT,
SUBNETC NVARCHAR(50) COLLATE database_default
)

-- Insert into filter id of the SubnetC to increase performence for event table
INSERT INTO #SUBNETCFILTERTABLE
SELECT DISTINCT
ipid,
ip.SubNetC
FROM
APM.IP AS ip (NOLOCK)
JOIN APM.GetMultiParameters(CASE WHEN LEN(@INCLUDESUBNET) &gt; 0 THEN @INCLUDESUBNET ELSE N'%' END, N'') AS p1 ON (ip.SubnetC LIKE p1.Value)
LEFT OUTER JOIN APM.GetMultiParameters(CASE WHEN LEN(@EXCLUDESUBNET) &gt; 0 THEN @EXCLUDESUBNET ELSE N'Fake' END, N'') AS p2 ON (ip.SubnetC LIKE p2.Value)
WHERE
--Exclude subnets which have correspondance in @EXCLUDESUBNET parameter
p2.typeId IS NULL

CREATE TABLE #CLIENTEVENT
(
CSEVENTID INT,
SOURCEID INT
)

INSERT INTO #CLIENTEVENT
SELECT
e.CSEventId,
e.SourceId
FROM
APM.CSEvent (NOLOCK) AS e
JOIN #SOURCEMACHINEFILTERTABLE AS f1 ON (f1.VALUEID = e.SourceId AND f1.TYPEID = 1)
JOIN #SOURCEMACHINEFILTERTABLE AS f2 ON (f2.VALUEID = e.MachineId AND f2.TYPEID = 2)
JOIN #SUBNETCFILTERTABLE AS f3 ON e.ipid = f3.IPID
JOIN #PMSTATUSFILTERTABLE AS f4 ON (f4.VALUEID = e.PMStatus)
WHERE
e.ClassType = N'Performance'
AND e.UTCDate &gt;= @STARTDATE
AND e.UTCDate &lt; @ENDDATE

CREATE TABLE #LATENCIES
(
ID INT,
MIN INT,
MAX INT
)

INSERT INTO #LATENCIES VALUES (1, 0, 100)
INSERT INTO #LATENCIES VALUES (2, 101, 300)
INSERT INTO #LATENCIES VALUES (3, 301, 600)
INSERT INTO #LATENCIES VALUES (4, 601, 1000)
INSERT INTO #LATENCIES VALUES (5, 1001, 2000)
INSERT INTO #LATENCIES VALUES (6, 2001, 99999999)

;WITH AJAXEvents AS
(
SELECT
e.CSEVENTID,
e.SOURCEID,
ajax.TotalTime AS TotalTime,
ajax.Latency AS Latency
FROM
#CLIENTEVENT AS e
JOIN APM.CSAJAX AS ajax (NOLOCK) ON e.CSEVENTID = ajax.CSEventId
),
JSEvents AS
(
SELECT
e.CSEVENTID,
e.SOURCEID,
js.TotalTime AS TotalTime,
NULL AS Latency
FROM
#CLIENTEVENT AS e
JOIN APM.CSJSCRIPTEVENT AS js (NOLOCK) ON e.CSEVENTID = js.CSEventId

),
PageEvents AS
(
SELECT
e.CSEVENTID,
e.SOURCEID,
p.TotalTime AS TotalTime,
p.Latency AS Latency
FROM
#CLIENTEVENT AS e
JOIN APM.CSPAGEEVENT AS p (NOLOCK) ON e.CSEVENTID = p.CSEventId
),
UnionEvents AS
(
SELECT * from AJAXEvents
UNION ALL
SELECT * from JSEvents
UNION ALL
SELECT * from PageEvents
),
EventAggregation AS
(
SELECT
SourceId,
MAX(TotalTime) / 1000.0 AS TotalTime,
AVG(Latency) AS Latency
FROM UnionEvents
GROUP BY
CSEventId, SourceId
),
NumberedDataSet AS
(
SELECT
ROW_NUMBER() OVER(ORDER BY COUNT(CASE
WHEN @ORDERBY = 1 AND L.ID = 1 THEN 1
WHEN @ORDERBY = 2 AND L.ID = 2 THEN 1
WHEN @ORDERBY = 3 AND L.ID = 3 THEN 1
WHEN @ORDERBY = 4 AND L.ID = 4 THEN 1
WHEN @ORDERBY = 5 AND L.ID = 5 THEN 1
WHEN @ORDERBY = 6 THEN 1
END) DESC) AS Id,
SourceId,
COUNT(CASE WHEN L.ID = 1 THEN 1 END) AS EventCount1,
COUNT(CASE WHEN L.ID = 2 THEN 1 END) AS EventCount2,
COUNT(CASE WHEN L.ID = 3 THEN 1 END) AS EventCount3,
COUNT(CASE WHEN L.ID = 4 THEN 1 END) AS EventCount4,
COUNT(CASE WHEN L.ID = 5 THEN 1 END) AS EventCount5,
COUNT(CASE WHEN L.ID = 6 THEN 1 END) AS EventCount6,
AVG(CASE WHEN L.ID = 1 THEN TotalTime END) AS EventDuration1,
AVG(CASE WHEN L.ID = 2 THEN TotalTime END) AS EventDuration2,
AVG(CASE WHEN L.ID = 3 THEN TotalTime END) AS EventDuration3,
AVG(CASE WHEN L.ID = 4 THEN TotalTime END) AS EventDuration4,
AVG(CASE WHEN L.ID = 5 THEN TotalTime END) AS EventDuration5,
COUNT(*) AS EventCount
FROM EventAggregation AS EA
JOIN #LATENCIES AS L ON COALESCE(EA.Latency, 99999999) &gt;= L.MIN AND COALESCE(EA.Latency, 99999999) &lt;= L.MAX
GROUP BY SourceId
)
--Select each range info into separate row to provide better view in report charts
SELECT
sr.Id,
r.n AS LatencyRange,
sr.EventCount,
s.Source,
sr.SourceId,
(CASE WHEN r.n = 1 THEN sr.EventCount1 END) AS EventCount1,
(CASE WHEN r.n = 2 THEN sr.EventCount2 END) AS EventCount2,
(CASE WHEN r.n = 3 THEN sr.EventCount3 END) AS EventCount3,
(CASE WHEN r.n = 4 THEN sr.EventCount4 END) AS EventCount4,
(CASE WHEN r.n = 5 THEN sr.EventCount5 END) AS EventCount5,
(CASE WHEN r.n = 1 THEN COALESCE(sr.EventDuration1, 0) END) AS EventDuration1,
(CASE WHEN r.n = 2 THEN COALESCE(sr.EventDuration2, 0) END) AS EventDuration2,
(CASE WHEN r.n = 3 THEN COALESCE(sr.EventDuration3, 0) END) AS EventDuration3,
(CASE WHEN r.n = 4 THEN COALESCE(sr.EventDuration4, 0) END) AS EventDuration4,
(CASE WHEN r.n = 5 THEN COALESCE(sr.EventDuration5, 0) END) AS EventDuration5
FROM
NumberedDataSet AS sr
JOIN APM.Source AS s (NOLOCK) ON sr.SourceId = s.SourceId,
APM.fn_nums(5) AS r
ORDER BY
sr.Id,
r.n
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.ClientLatencyDistributionSubReport'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.ClientLatencyDistributionSubReport AS RETURN 1')
END
GO

/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME:ClientLatencyDistributionSubReport */
/* USED IN: Client Latency Distribution for sub report */
/* INPUT PARAMETERS: */
/* @STARTDATE - Start date of the priod */
/* @ENDDATE - End date of the period */
/* @SOURCEID - Id of the source */
/* @MACHINEIDS - List of machine Id, separated by comma. Exp: '4,5,6' */
/* @SUBNETC - List subnet type C, selected by user */
/* @ORDERBY - Specifies field to which sorting should be applayed */
/* 1. Event Count */
/* 2. Problems Count */
/* 4. Event Duration */
/* 5. Latency */
/************************************************************************************/
ALTER PROCEDURE APM.ClientLatencyDistributionSubReport
@STARTDATE DATETIME,
@ENDDATE DATETIME,
@SOURCEID INT,
@MACHINEIDS NVARCHAR(MAX),
@INCLUDESUBNET NVARCHAR(MAX),
@EXCLUDESUBNET NVARCHAR(MAX),
@ORDERBY INT,
@PMSTATUS NVARCHAR(50)
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON

/****************************************************************************************/
/* ASSISTING TEMP TABLES */
/****************************************************************************************/

SELECT
@INCLUDESUBNET = REPLACE(@INCLUDESUBNET, N'*', N'%'),
@EXCLUDESUBNET = REPLACE(@EXCLUDESUBNET, N'*', N'%')

-- Filter table, which contains machine ids and source ids
-- valueId filter value for machine id
CREATE TABLE #MACHINEFILTERTABLE(
VALUEID INT
)

INSERT
INTO #MACHINEFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@MACHINEIDS, N'') AS p

-- Filter table, which contains PM Statuses of Events
CREATE TABLE #PMSTATUSFILTERTABLE(
VALUEID INT
)

-- Fill table #PMSTATUSFILTERTABLE
INSERT
INTO #PMSTATUSFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@PMSTATUS, N'') AS p

-- Filter table for SubnetC values
CREATE TABLE #SUBNETCFILTERTABLE
(
IPID INT,
SUBNETC NVARCHAR(50) COLLATE database_default
)

-- Insert into filter id of the SubnetC to increase performence for event table
INSERT INTO #SUBNETCFILTERTABLE
SELECT
ipid,
ip.SubNetC
FROM
APM.IP AS ip (NOLOCK)
JOIN APM.GetMultiParameters(CASE WHEN LEN(@INCLUDESUBNET) &gt; 0 THEN @INCLUDESUBNET ELSE N'%' END, N'') AS p1 ON (ip.SubnetC LIKE p1.Value)
LEFT OUTER JOIN APM.GetMultiParameters(CASE WHEN LEN(@EXCLUDESUBNET) &gt; 0 THEN @EXCLUDESUBNET ELSE N'Fake' END, N'') AS p2 ON (ip.SubnetC LIKE p2.Value)
WHERE
--Exclude subnets which have correspondance in @EXCLUDESUBNET parameter
p2.typeId IS NULL

CREATE TABLE #CLIENTEVENT
(
CSEVENTID INT,
CSEVENTGROUPID INT,
SUBNETC NVARCHAR(50) collate database_default
)

INSERT INTO #CLIENTEVENT
SELECT
e.CSEventId,
e.CSEventGroupId,
f3.SUBNETC
FROM
APM.CSEvent (NOLOCK) AS e
JOIN #MACHINEFILTERTABLE AS f1 ON f1.VALUEID = e.MachineId
JOIN #PMSTATUSFILTERTABLE AS f2 ON (f2.VALUEID = e.PMStatus)
JOIN #SUBNETCFILTERTABLE AS f3 ON e.ipid = f3.IPID
WHERE
e.ClassType = N'Performance'
AND e.SourceId = @SOURCEID
AND e.UTCDate &gt;= @STARTDATE
AND e.UTCDate &lt; @ENDDATE

/****************************************************************************************/
/* MAIN QUERY */
/****************************************************************************************/
-- Aggregate AJAX by event id, as several synchronous ajax call can belong to one event
;WITH AJAXEvents AS
(
SELECT
e.CSEVENTID,
-- Aggregation by Total Time make no difference, as for synch ajaxes total time will
-- be taken from JS event, and for asynch AJAX here can be only one row
AVG(ajax.TotalTime) AS TotalTime,
-- For synch ajax select average latency among calls, for asynch here will be only one row
AVG(ajax.Latency) AS Latency
FROM
#CLIENTEVENT AS e
JOIN APM.CSAJAX AS ajax (NOLOCK) ON e.CSEVENTID = ajax.CSEventId
GROUP BY
e.CSEVENTID
),
-- For each subnet choose its average latency and event duration
SubNetCStatistics AS
(
SELECT
e.SUBNETC,
COUNT(e.CSEVENTID) AS EventCount,
COUNT(DISTINCT e.CSEVENTGROUPID) AS ProblemCount,
-- Event could by either Page or JavaScript or Asycnh Ajax. Row in AJAX table will be presented for both synch and asynch ajaxes,
-- But for synch AJAXes only latency should by taken and Total Time should by taken from either Page event or Jscript event
AVG(COALESCE(p.TotalTime, COALESCE(js.TotalTime, ajax.TotalTime)))/1000.0 AS EventDuration,
--Latency could be either in page event or in Ajax event
AVG(COALESCE(p.Latency, ajax.Latency)) AS Latency
FROM
#CLIENTEVENT AS e
LEFT OUTER JOIN AJAXEvents AS ajax ON ajax.CSEventId = e.CSEVENTID
LEFT OUTER JOIN APM.CSPageEvent AS p (NOLOCK) ON p.CSEventId = e.CSEVENTID
LEFT OUTER JOIN APM.CSJScriptEvent AS js (NOLOCK) ON e.CSEVENTID = js.CSEventId
GROUP BY
e.SUBNETC
)
-- Select top 5 rows, ordered by specified parameter @ORDERBY
SELECT TOP(5)
ROW_NUMBER() OVER(ORDER BY (CASE @ORDERBY
WHEN 1 THEN EventCount
WHEN 2 THEN ProblemCount
WHEN 3 THEN EventDuration
WHEN 4 THEN Latency
END) DESC) AS Id,
SubNetC AS Client,
EventCount,
ProblemCount,
EventDuration,
Latency
FROM
SubNetCStatistics
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.ApplicationAnalysisJScriptWithAjaxCalls'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.ApplicationAnalysisJScriptWithAjaxCalls AS RETURN 1')
END
GO

/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: ApplicationAnalysisJScriptWithAjaxCalls */
/* USED IN: Application Analysis report for TOP slowest Ajax, top slowest JS, */
/* TOP largest AJAX */
/* INPUT PARAMETERS: */
/* @STARTDATE - Start date of the priod */
/* @ENDDATE - End date of the period */
/* @SOURCEID - SourceId */
/* @MACHINEIDS - List of machine Id, separated by comma. Exp: '4,5,6' */
/* @INCLUDESUBNET - List masks, which should be included */
/* @EXCLUDESUBNET - List masks, which should be excluded */
/* @THRESHOLD - Event threshold */
/* @ORDERBY1 - Specifies field to which sorting for largest AJAX calls */
/* should be applayed. Possible Values: */
/* 1. Event Count */
/* 2. Request Size */
/* 3. Response Size */
/* 4. Total Size */
/* 5. Total Time */
/* @ORDERBY2 - Specifies field to which sorting for slowest AJAX calls */
/* should be applayed. Possible Values: */
/* 1. Event Count */
/* 2. Client Time */
/* 3. Network Time */
/* 4. Server Time */
/* 5. Total Time */
/* 6. Request Size */
/* 7. Response Size */
/* 8. Latency */
/* @ORDERBY3 - Specifies field to which sorting for slowest JavaScript */
/* should be applayed. Possible Values: */
/* 1. Event Count */
/* 2. AJAX Call Count */
/* 3. Client Time */
/* 4. Network Time */
/* 5. Server Time */
/* 6. Total Time */
/* 7. Avg Event Size */
/* 8. Latency */
/************************************************************************************/
ALTER PROCEDURE APM.ApplicationAnalysisJScriptWithAjaxCalls
@STARTDATE DATETIME,
@ENDDATE DATETIME,
@SOURCEID NVARCHAR(MAX),
@MACHINEIDS NVARCHAR(MAX),
@INCLUDESUBNET NVARCHAR(MAX),
@EXCLUDESUBNET NVARCHAR(MAX),
@PMSTATUS NVARCHAR(50),
@ORDERBY1 INT,
@ORDERBY2 INT,
@ORDERBY3 INT
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON

/****************************************************************************************/
/* ASSISTING TEMP TABLES */
/****************************************************************************************/

SELECT
@INCLUDESUBNET = REPLACE(@INCLUDESUBNET, N'*', N'%'),
@EXCLUDESUBNET = REPLACE(@EXCLUDESUBNET, N'*', N'%')

-- Filter table, which contains machine ids and source ids
-- valueId filter value - machine id
CREATE TABLE #MACHINEFILTERTABLE(
VALUEID INT
)

-- Fill table #SOURCEMACHINEFILTERTABLE
INSERT
INTO #MACHINEFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@MACHINEIDS, N'') AS p

-- Filter table, which contains PM Statuses of Events
CREATE TABLE #PMSTATUSFILTERTABLE(
VALUEID INT
)

-- Fill table #PMSTATUSFILTERTABLE
INSERT
INTO #PMSTATUSFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@PMSTATUS, N'') AS p

-- Filter table for SubnetC values
CREATE TABLE #SUBNETCFILTERTABLE
(
IPID INT,
SUBNETC NVARCHAR(50) collate database_default
)

-- Insert into filter id of the SubnetC to increase performance for event table
INSERT INTO #SUBNETCFILTERTABLE
SELECT DISTINCT
ipid,
SubNetC
FROM
IP AS ip (NOLOCK)
JOIN APM.GetMultiParameters(CASE WHEN LEN(@INCLUDESUBNET) &gt; 0 THEN @INCLUDESUBNET ELSE N'%' END, N'') AS p1 ON (ip.SubnetC LIKE p1.Value)
LEFT OUTER JOIN APM.GetMultiParameters(CASE WHEN LEN(@EXCLUDESUBNET) &gt; 0 THEN @EXCLUDESUBNET ELSE N'Fake' END, N'') AS p2 ON (ip.SubnetC LIKE p2.Value)
WHERE
--Exclude subnets which have correspondance in @EXCLUDESUBNET parameter
p2.typeId IS NULL

CREATE TABLE #CLIENTEVENTS
(
CSEVENTID INT,
PAGEURI NVARCHAR(255) COLLATE database_default,
CLASSTYPE NVARCHAR(50) COLLATE database_default,
CSEVENTGROUPID INT
)

INSERT INTO #CLIENTEVENTS
SELECT
e.CSEventId,
e.PageUri,
e.ClassType,
e.CSEventGroupId
FROM
APM.CSEvent (NOLOCK) AS e
JOIN #MACHINEFILTERTABLE AS f ON (f.VALUEID = e.MachineId)
JOIN #SUBNETCFILTERTABLE AS f2 ON e.ipid = f2.IPID
JOIN #PMSTATUSFILTERTABLE AS f3 ON (f3.VALUEID = e.PMStatus)
WHERE
e.sourceId = @SOURCEID
AND PageUri IS NOT NULL
AND e.UTCDate &gt;= @STARTDATE
AND e.UTCDate &lt; @ENDDATE
AND e.EventClass &lt;&gt; N'CSMPMonitorLog'

CREATE TABLE #AJAXCALLS
(
ID INT,
CSEVENTID INT,
PAGEURI NVARCHAR(255) COLLATE database_default,
AJAXACTION NVARCHAR(255) COLLATE database_default,
TOTALTIME DECIMAL(35, 0),
NETWORKTIME DECIMAL(35, 0),
SERVERTIME DECIMAL(35, 0),
RESPONSETIME DECIMAL(35, 0),
REQUESTSIZE DECIMAL(35, 0),
RESPONSESIZE DECIMAL(35, 0),
LATENCY BIGINT,
TOTALAJAXCALLCOUNT INT,
AVGAJAXCALLDURATION FLOAT,
SYNCHRONOUS BIT
)
-- Several synchronous Ajax calls could belong to one event, in that case only heaviest (by Total duration) should be taken.
-- Numerate Ajax calls for each event by Total Time in descending order.
-- Next step is to take ajax calls with id equal to 1.
-- For asynch ajaxes all rows will be with id = 1
;WITH AjaxCallsInternal AS
(
SELECT
ROW_NUMBER() OVER(PARTITION BY E.CSEVENTID ORDER BY ajax.TOTALTIME DESC, ajax.CSAJAXId) AS Id,
e.CSEVENTID,
e.PAGEURI,
ajax.URI,
COALESCE(ajax.TOTALTIME, 0) AS TotalTime,
COALESCE(ajax.NETWORKTIME, 0) AS NetworkTime,
COALESCE(ajax.SERVERTIME, 0) AS ServerTime,
COALESCE(ajax.RESPONSETIME, 0) AS ResponseTime,
COALESCE(ajax.REQUESTSIZE, 0) AS RequestSize,
COALESCE(ajax.RESPONSESIZE, 0) AS ResponseSize,
ajax.LATENCY,
COUNT(CSAJAXId) OVER(PARTITION BY e.CSEVENTID) AS TotalAjaxCallCount,
ajax.SYNCHRONOUS
FROM
APM.CSAJAX AS ajax (NOLOCK)
JOIN #CLIENTEVENTS AS e ON e.CSEVENTID = ajax.CSEVENTID
),
AjaxCallsWithAvg AS
(
SELECT
Id,
CSEVENTID,
PAGEURI,
URI,
TotalTime,
NetworkTime,
ServerTime,
ResponseTime,
RequestSize,
ResponseSize,
LATENCY,
TotalAjaxCallCount,
--calculate avg only for haviest ajax calls by ms
AVG(CASE Id WHEN 1 THEN TotalTime END) OVER() AS AvgAjaxCallDuration,
SYNCHRONOUS
FROM
AjaxCallsInternal
)
INSERT INTO #AJAXCALLS
SELECT * FROM AjaxCallsWithAvg

/****************************************************************************************/
/* MAIN QUERY */
/****************************************************************************************/
--Group information over ajax calls
;WITH HeaviestAjaxCalls AS
(
SELECT
PAGEURI,
AJAXACTION,
SYNCHRONOUS,
COUNT(CSEVENTID) AS EventCount,
AVG(TOTALTIME)/1000.0 AS TotalTime,
AVG(NETWORKTIME)/1000.0 AS NetworkTime,
AVG(SERVERTIME)/1000.0 AS ServerTime,
AVG(RESPONSETIME)/1000.0 AS ResponseTime,
AVG(REQUESTSIZE)/1024.0 AS RequestSize,
AVG(RESPONSESIZE)/1024.0 AS ResponseSize,
AVG(LATENCY) AS Latency,
MAX(REQUESTSIZE + RESPONSESIZE)/1024.0 AS MaxAjaxCall,
MAX(TOTALTIME)/1000.0 AS MaxAjaxCallDuration,
SUM(TOTALAJAXCALLCOUNT) AS TotalAjaxCallCount,
MIN(AVGAJAXCALLDURATION) / 1000.0 AS AvgAjaxCallDuration
FROM
#AJAXCALLS
WHERE
--Select only heaviest AJAX calls for each event
ID = 1
GROUP BY
PAGEURI,
AJAXACTION,
SYNCHRONOUS
),
-- Select information for top 10 Largest AJAX calls
LargestAjaxCalls AS
(
SELECT
ROW_NUMBER() OVER (ORDER BY CASE @ORDERBY1
WHEN 1 THEN EventCount
WHEN 2 THEN RequestSize
WHEN 3 THEN ResponseSize
WHEN 4 THEN COALESCE(RequestSize, 0) + COALESCE(ResponseSize, 0)
WHEN 5 THEN TotalTime
END DESC) AS Id,
PageUri,
AjaxAction,
EventCount,
RequestSize,
ResponseSize,
TotalTime,
TotalAjaxCallCount,
SUM(EventCount) OVER() AS TotalAjaxEventCount,
AVG(RequestSize + ResponseSize) OVER() AS AvgAjaxCallSize,
MAX(MaxAjaxCall) OVER() AS LargestAjaxCallSize
FROM
HeaviestAjaxCalls AS h
),
--Select information for top Slowest Ajax Calls (only asynch AJAXes)
SlowestAjaxCalls AS
(
SELECT
ROW_NUMBER() OVER (ORDER BY CASE @ORDERBY2
WHEN 1 THEN EventCount
WHEN 2 THEN TotalTime - (NetworkTime + ResponseTime + ServerTime)
WHEN 3 THEN NetworkTime + ResponseTime
WHEN 4 THEN ServerTime
WHEN 5 THEN TotalTime
WHEN 6 THEN RequestSize
WHEN 7 THEN ResponseSize
WHEN 8 THEN Latency
END DESC) AS Id,
PageUri,
AjaxAction,
EventCount,
NetworkTime + ResponseTime AS NetworkTime,
ServerTime,
TotalTime - (NetworkTime + ResponseTime + ServerTime) AS ClientTime,
TotalTime,
RequestSize,
ResponseSize,
Latency,
SUM(EventCount) OVER() AS TotalAjaxEventCount,
AvgAjaxCallDuration,
MAX(MaxAjaxCallDuration) OVER() AS MaxAjaxCallDuration
FROM
HeaviestAjaxCalls AS h
WHERE
-- Select only Asynch AJAXes
Synchronous = 0
),
JavaScriptActions AS
(
SELECT
js.ACTION,
e.PAGEURI,
COUNT(e.CSEVENTID) AS EventCount,
SUM(COALESCE(ajax.TOTALAJAXCALLCOUNT, 0)) AS AjaxCallCount,
AVG(COALESCE(ajax.NETWORKTIME + ajax.RESPONSETIME, 0))/1000.0 AS JSNetworkTime,
AVG(COALESCE(ajax.SERVERTIME, 0))/1000.0 AS JSServerTime,
-- Clinet time is calculated as jsevent time minus ajax call time
-- If JavaScript function has no ajax calls, then all time consider to be client time
AVG(js.TOTALTIME - COALESCE(ajax.TOTALTIME, 0))/1000.0 AS JSClientTime,
AVG(js.TOTALTIME)/1000.0 AS JSTotalTime,
AVG(REQUESTSIZE + RESPONSESIZE)/1024.0 AS AvgSize,
AVG(LATENCY) AS Latency,
MAX(js.TOTALTIME)/1000.0 AS JSMaxTime
FROM
APM.CSJScriptEvent AS js (NOLOCK)
JOIN #CLIENTEVENTS AS e ON e.CSEVENTID = js.CSEVENTID
-- If Java script has ajax events, condition id = 1 alows to select largest (by total time) ajax call
LEFT OUTER JOIN #AJAXCALLS AS ajax ON (ajax.ID = 1 AND ajax.CSEVENTID = js.CSEVENTID)
GROUP BY
js.ACTION,
e.PAGEURI
),
-- Order java script info by specified parameter
SlowestJScript AS
(
SELECT
ROW_NUMBER() OVER(ORDER BY (CASE @ORDERBY3
WHEN 1 THEN EventCount
WHEN 2 THEN AJAXCallCount
WHEN 3 THEN JSClientTime
WHEN 4 THEN JSNetworkTime
WHEN 5 THEN JSServerTime
WHEN 6 THEN JSTotalTime
WHEN 7 THEN AvgSize
WHEN 8 THEN Latency
END) DESC) AS id,
Action AS JSAction,
PageUri,
EventCount,
AJAXCallCount,
JSClientTime,
JSNetworkTime,
JSServerTime,
JSTotalTime,
AvgSize,
Latency,
SUM(EventCount) OVER() AS TotalJSEventCount,
MAX(JSMaxTime) OVER() AS JScriptMaxTime,
-- Calculate average time for all java script events
(SUM(JSTotalTime*EventCount) OVER())/(SUM(EventCount) OVER()) AS AverageJScriptTime
FROM
JavaScriptActions
)
--select TOP 10 rows from each query
SELECT
[top].n AS Id,
-- Largest Ajax Calls
la.PageUri AS la_PageUri,
la.AjaxAction AS la_AjaxAction,
la.EventCount AS la_EventCount,
la.RequestSize AS la_RequestSize,
la.ResponseSize AS la_ResponseSize,
la.TotalTime AS la_TotalTime,
-- End Largest Ajax Calls
-- Slowest AJAX Calls
sa.PageUri AS sa_PageUri,
sa.AjaxAction AS sa_AjaxAction,
sa.EventCount AS sa_EventCount,
sa.NetworkTime AS sa_NetworkTime,
sa.ServerTime AS sa_ServerTime,
sa.ClientTime AS sa_ClientTime,
sa.TotalTime AS sa_TotalTime,
sa.RequestSize AS sa_RequestSize,
sa.ResponseSize AS sa_ResponseSize,
sa.Latency AS sa_Latency,
sa.TotalAjaxEventCount AS sa_TotalAsynchAjaxesCount,
-- End Slowest AJAX Calls
-- Slowest JavaScript
js.JSAction AS js_Action,
js.PageUri AS js_PageUri,
js.EventCount AS js_EventCount,
js.AJAXCallCount AS js_AJAXCallCount,
js.JSClientTime AS js_JSClientTime,
js.JSNetworkTime AS js_JSNetworkTime,
js.JSServerTime AS js_JSServerTime,
js.JSTotalTime AS js_JSTotalTime,
js.AvgSize AS js_AvgSize,
js.Latency AS js_Latency,
js.TotalJSEventCount,
-- End Slowest JavaScript
-- Summary information
la.TotalAjaxCallCount,
la.TotalAjaxEventCount,
la.AvgAjaxCallSize,
la.LargestAjaxCallSize,
sa.AvgAjaxCallDuration,
sa.MaxAjaxCallDuration,
js.JScriptMaxTime,
js.AverageJScriptTime
-- End Summary Information
FROM
APM.fn_nums(10) AS [top]
LEFT OUTER JOIN LargestAjaxCalls AS la ON [top].n = la.Id
LEFT OUTER JOIN SlowestAjaxCalls AS sa ON [top].n = sa.Id
LEFT OUTER JOIN SlowestJScript AS js ON [top].n = js.Id
ORDER BY
Id
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.ApplicationAnalysisTopPages'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.ApplicationAnalysisTopPages AS RETURN 1')
END
GO

/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: ApplicationAnalysisTopPages */
/* USED IN: Application Analysis report for TOP 10 slowest ans top 10 largest pages */
/* INPUT PARAMETERS: */
/* @STARTDATE - Start date of the priod */
/* @ENDDATE - End date of the period */
/* @SOURCEID - SourceId */
/* @MACHINEIDS - List of machine Id, separated by comma. Exp: '4,5,6' */
/* @INCLUDESUBNET - Subnet masks list, which should be included */
/* @EXCLUDESUBNET - Subnet masks list, which should be excluded */
/* @ORDERBY1 - Specifies field to which sorting for largest pages */
/* should be applayed. Possible Values: */
/* 1. Event Count */
/* 2. Image Size */
/* 3. CSS Size */
/* 4. HTC Behavior Size */
/* 5. Script Size */
/* 6. HTML Size */
/* 7. AJAX Size */
/* 8. Avg Page Size */
/* 9. Event Duration Time */
/* @ORDERBY2 - Specifies field to which sorting for slowest pages */
/* should be applayed. Possible Values: */
/* 1. Event Count */
/* 2. Network Time */
/* 3. Server Time */
/* 4. DOM Time */
/* 5. Peripheral Time */
/* 6. OnLoad Time */
/* 7. Event Duration */
/************************************************************************************/
ALTER PROCEDURE APM.ApplicationAnalysisTopPages
@STARTDATE DATETIME,
@ENDDATE DATETIME,
@SOURCEID NVARCHAR(MAX),
@MACHINEIDS NVARCHAR(MAX),
@INCLUDESUBNET NVARCHAR(MAX),
@EXCLUDESUBNET NVARCHAR(MAX),
@PMSTATUS NVARCHAR(50),
@ORDERBY1 INT,
@ORDERBY2 INT
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON

/****************************************************************************************/
/* ASSISTING TEMP TABLES */
/****************************************************************************************/
SELECT
@INCLUDESUBNET = REPLACE(@INCLUDESUBNET, N'*', N'%'),
@EXCLUDESUBNET = REPLACE(@EXCLUDESUBNET, N'*', N'%')

-- Filter table, which contains machine ids and source ids
-- valueId filter value - machine id
CREATE TABLE #MACHINEFILTERTABLE(
VALUEID INT
)

-- Fill table #SOURCEMACHINEFILTERTABLE
INSERT
INTO #MACHINEFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@MACHINEIDS, N'') AS p

-- Filter table, which contains PM Statuses of Events
CREATE TABLE #PMSTATUSFILTERTABLE(
VALUEID INT
)

-- Fill table #PMSTATUSFILTERTABLE
INSERT
INTO #PMSTATUSFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@PMSTATUS, N'') AS p

-- Filter table for SubnetC values
CREATE TABLE #SUBNETCFILTERTABLE
(
IPID INT,
SUBNETC NVARCHAR(50) COLLATE DATABASE_DEFAULT
)

-- Insert into filter id of the SubnetC to increase performance for event table
INSERT INTO #SUBNETCFILTERTABLE
SELECT DISTINCT
ipid,
SubNetC
FROM
APM.IP AS ip (NOLOCK)
JOIN APM.GetMultiParameters(CASE WHEN LEN(@INCLUDESUBNET) &gt; 0 THEN @INCLUDESUBNET ELSE N'%' END, N'') AS p1 ON (ip.SubnetC LIKE p1.Value)
LEFT OUTER JOIN APM.GetMultiParameters(CASE WHEN LEN(@EXCLUDESUBNET) &gt; 0 THEN @EXCLUDESUBNET ELSE N'Fake' END, N'') AS p2 ON (ip.SubnetC LIKE p2.Value)
WHERE
--Exclude subnets which have correspondance in @EXCLUDESUBNET parameter
p2.typeId IS NULL

CREATE TABLE #CLIENTEVENTS
(
CSEVENTID INT,
PAGEURI NVARCHAR(255) COLLATE DATABASE_DEFAULT,
CLASSTYPE NVARCHAR(50) COLLATE DATABASE_DEFAULT,
CSEVENTGROUPID INT
)

INSERT INTO #CLIENTEVENTS
SELECT
e.CSEVENTID,
e.PAGEURI,
e.CLASSTYPE,
e.CSEVENTGROUPID
FROM
APM.CSEvent (NOLOCK) AS e
JOIN #MACHINEFILTERTABLE AS f ON (f.VALUEID = e.MACHINEID)
JOIN #SUBNETCFILTERTABLE AS f2 ON e.ipid = f2.IPID
JOIN #PMSTATUSFILTERTABLE AS f3 ON (f3.VALUEID = e.PMSTATUS)
WHERE
e.SOURCEID = @SOURCEID
AND e.PAGEURI IS NOT NULL
AND e.UTCDATE &gt;= @STARTDATE
AND e.UTCDATE &lt; @ENDDATE
AND e.EVENTCLASS = N'CSMPMonitorLog'

/****************************************************************************************/
/* MAIN QUERY */
/****************************************************************************************/
;WITH AjaxCalls AS
(
SELECT
e.CSEVENTID,
SUM(ajax.RESPONSESIZE) AS ResponseSize,
SUM(ajax.REQUESTSIZE) AS RequestSize
FROM
APM.CSAJAX AS ajax (NOLOCK)
JOIN #CLIENTEVENTS AS e ON e.CSEVENTID = ajax.CSEventId
GROUP BY
e.CSEVENTID
),
-- Select information about page content size for each event (this information is available only for page events)
PeripheralDetails AS
(
SELECT
b.CSEventId,
COALESCE(b.Image, 0) AS Image,
COALESCE(b.HtcBehavior, 0) AS HtcBehavior,
COALESCE(b.Script, 0) AS Script,
COALESCE(b.html, 0) AS html,
COALESCE(b.CssStyle, 0) AS CssStyle,
COALESCE(ajax.ResponseSize + ajax.REQUESTSIZE, 0) AS Ajax,
COALESCE(b.Image, 0) + COALESCE(b.HtcBehavior, 0) + COALESCE(b.Script, 0)
+ COALESCE(b.html, 0) + COALESCE(b.CssStyle, 0)
+ COALESCE(ajax.ResponseSize + ajax.REQUESTSIZE, 0) AS TotalSize
FROM
(
SELECT
e.CSEVENTID,
p.TYPE,
p.TOTALSIZE
FROM
#CLIENTEVENTS AS e
JOIN APM.CSPeripheral AS p (NOLOCK) ON e.CSEVENTID = p.CSEVENTID
)AS A
PIVOT (SUM(TotalSize) FOR Type IN (Image, HtcBehavior, Script, html, CssStyle)) AS b
LEFT OUTER JOIN AjaxCalls AS ajax ON (ajax.CSEVENTID = b.CSEVENTID)
),
-- Group page events information by pages
PageEvents AS
(
SELECT
e.PAGEURI,
COUNT(e.CSEVENTID) AS EventCount,
-- All null values in time segments should be changed to 0, to provide convergence with average total time
AVG(COALESCE(p.NetworkTime, 0))/1000.0 AS NetworkTime,
AVG(COALESCE(p.ServerTime, 0))/1000.0 AS ServerTime,
AVG(COALESCE(p.DomTime, 0))/1000.0 AS DomTime,
AVG(COALESCE(p.PeripheralTime, 0))/1000.0 AS PeripheralTime,
AVG(COALESCE(p.OnLoadTime, 0))/1000.0 AS OnLoadTime,
AVG(p.TotalTime)/1000.0 AS EventDuration,
MAX(p.TotalTime)/1000.0 AS MaxEventDuration,
AVG(d.TotalSize)/1024.0 AS AveragePageSize,
MAX(d.TotalSize)/1024.0 AS MaxPageSize,
AVG(d.Image)/1024.0 AS ImageSize,
AVG(d.HtcBehavior)/1024.0 AS HtcBehaviorSize,
AVG(d.Script)/1024.0 AS ScriptSize,
AVG(d.html)/1024.0 AS HTMLSize,
AVG(d.CssStyle)/1024.0 AS CssStyleSize,
AVG(Ajax)/1024.0 AS AJAXCallSize
FROM
#CLIENTEVENTS AS e
JOIN APM.CSPageEvent AS p (NOLOCK) ON p.CSEventId = e.CSEVENTID
LEFT OUTER JOIN PeripheralDetails AS d ON d.CSEventId = e.CSEVENTID
GROUP BY
e.PAGEURI
),
-- Select information for top 10 largest pages
LargesPage AS
(
SELECT
ROW_NUMBER() OVER(ORDER BY (CASE @ORDERBY1
WHEN 1 THEN EventCount
WHEN 2 THEN ImageSize
WHEN 3 THEN CssStyleSize
WHEN 4 THEN HtcBehaviorSize
WHEN 5 THEN ScriptSize
WHEN 6 THEN HTMLSize
WHEN 7 THEN AJAXCallSize
WHEN 8 THEN AveragePageSize
WHEN 9 THEN EventDuration
END) DESC) AS id,
PageUri,
EventCount,
ImageSize,
CssStyleSize,
HtcBehaviorSize,
ScriptSize,
HTMLSize,
AJAXCallSize,
AveragePageSize AS TotalSize,
EventDuration,
SUM(EventCount) OVER() AS TotalPageEventCount,
-- Select information about max page size and average page size over all application events,
-- This information will be shown in report summary information
MAX(MaxPageSize) OVER() AS MaxPageSize,
(SUM(AveragePageSize*EventCount) OVER())/(SUM(EventCount) OVER()) AS AveragePageSize
FROM
PageEvents
),
-- Select information for top 10 slowest pages
SlowestPage AS
(
SELECT
ROW_NUMBER() OVER(ORDER BY (CASE @ORDERBY2
WHEN 1 THEN EventCount
WHEN 2 THEN NetworkTime
WHEN 3 THEN ServerTime
WHEN 4 THEN DomTime
WHEN 5 THEN PeripheralTime
WHEN 6 THEN OnLoadTime
WHEN 7 THEN EventDuration
END) DESC) AS id,
PageUri,
EventCount,
NetworkTime,
ServerTime,
DomTime,
PeripheralTime,
OnLoadTime,
EventDuration AS TotalTime,
-- Select information about max page load time and average page load time over all application events,
-- This information will be shown in report summary information
MAX(MaxEventDuration) OVER() AS MaxPageLoadTime,
(SUM(EventDuration*EventCount) OVER())/(SUM(EventCount) OVER()) AS AveragePageLoadTime,
--Get ajax call flag
CASE WHEN EXISTS(
SELECT *
FROM #CLIENTEVENTS c
JOIN CSAJAX AS csaj (NOLOCK) ON csaj.cseventid = c.CSEVENTID
WHERE d.PageUri = c.PAGEURI
) THEN '*' ELSE ''
END AS Extension
FROM
PageEvents d
)
SELECT
[top].n AS Id,
-- Largest Pages
lp.PageUri AS lp_PageUri,
lp.EventCount AS lp_EventCount,
lp.ImageSize AS lp_ImageSize,
lp.CssStyleSize AS lp_CssStyleSize,
lp.HtcBehaviorSize AS lp_HtcBehaviorSize,
lp.ScriptSize AS lp_ScriptSize,
lp.HTMLSize AS lp_HTMLSize,
lp.AJAXCallSize AS lp_AJAXCallSize,
lp.TotalSize AS lp_TotalSize,
lp.EventDuration AS lp_EventDuration,
-- End Largest Pages
-- Slowest Pages
sp.PageUri AS sp_PageUri,
sp.EventCount AS sp_EventCount,
sp.NetworkTime AS sp_NetworkTime,
sp.ServerTime AS sp_ServerTime,
sp.DomTime AS sp_DomTime,
sp.PeripheralTime AS sp_PeripheralTime,
sp.OnLoadTime AS sp_OnLoadTime,
sp.TotalTime AS sp_TotalTime,
sp.Extension AS sp_Extension,
-- End Slowest Pages
-- Summary information
lp.TotalPageEventCount AS TotalPageEventCount,
lp.MaxPageSize,
lp.AveragePageSize,
sp.MaxPageLoadTime,
sp.AveragePageLoadTime
-- End Summary Information
FROM
APM.fn_nums(10) AS [top]
LEFT OUTER JOIN LargesPage AS lp ON [top].n = lp.Id
LEFT OUTER JOIN SlowestPage AS sp ON [top].n = sp.Id
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.SummaryPerformanceTopPages'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.SummaryPerformanceTopPages AS RETURN 1')
END
GO

/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: SummaryPerformanceTopPages */
/* USED IN: SummaryPerfTop5PageSubReport.rdl subreport */
/* INPUT PARAMETERS: */
/* @STARTDATE - Start date of the priod */
/* @ENDDATE - End date of the period */
/* @SOURCEID - SourceId */
/* @MACHINEIDS - List of machine Id, separated by comma. Exp: '4,5,6' */
/* @INCLUDESUBNET - Subnet masks list, which should be included */
/* @EXCLUDESUBNET - Subnet mask list, which should be excluded */
/* @THRESHOLD - Event threshold */
/************************************************************************************/
ALTER PROCEDURE APM.SummaryPerformanceTopPages
@STARTDATE DATETIME,
@ENDDATE DATETIME,
@SOURCEID INT,
@MACHINEIDS NVARCHAR(MAX),
@INCLUDESUBNET NVARCHAR(MAX),
@EXCLUDESUBNET NVARCHAR(MAX),
@THRESHOLD INT,
@PMSTATUS NVARCHAR(50)
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON

/****************************************************************************************/
/* ASSISTING TEMP TABLES */
/****************************************************************************************/

SELECT
@INCLUDESUBNET = REPLACE(@INCLUDESUBNET, N'*', N'%'),
@EXCLUDESUBNET = REPLACE(@EXCLUDESUBNET, N'*', N'%')

-- Filter table, which contains machine ids and source ids
-- valueId filter value - machine id
CREATE TABLE #MACHINEFILTERTABLE(
VALUEID INT
)

-- Fill table #SOURCEMACHINEFILTERTABLE
INSERT
INTO #MACHINEFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@MACHINEIDS, N'') AS p

-- Filter table for SubnetC values
CREATE TABLE #SUBNETCFILTERTABLE
(
IPID INT
)

-- Filter table, which contains PM Statuses of Events
CREATE TABLE #PMSTATUSFILTERTABLE(
VALUEID INT
)

-- Fill table #PMSTATUSFILTERTABLE
INSERT
INTO #PMSTATUSFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@PMSTATUS, N'') AS p

-- Insert into filter id of the SubnetC to increase performence for event table
INSERT INTO #SUBNETCFILTERTABLE
SELECT DISTINCT
ipid
FROM
APM.IP AS ip (NOLOCK)
JOIN APM.GetMultiParameters(CASE WHEN LEN(@INCLUDESUBNET) &gt; 0 THEN @INCLUDESUBNET ELSE N'%' END, N'') AS p1 ON (ip.SubnetC LIKE p1.Value)
LEFT OUTER JOIN APM.GetMultiParameters(CASE WHEN LEN(@EXCLUDESUBNET) &gt; 0 THEN @EXCLUDESUBNET ELSE N'Fake' END, N'') AS p2 ON (ip.SubnetC LIKE p2.Value)
WHERE
--Exclude subnets which have correspondance in @EXCLUDESUBNET parameter
p2.typeId IS NULL

CREATE TABLE #CLIENTEVENTS
(
CSEVENTID INT,
PAGEURI NVARCHAR(255) COLLATE DATABASE_DEFAULT
)

-- Filter Event Table by incoming parameters
INSERT INTO #CLIENTEVENTS
SELECT
e.CSEventId,
e.PageUri
FROM
APM.CSEVENT AS e (NOLOCK)
JOIN #MACHINEFILTERTABLE AS f ON (f.VALUEID = e.MachineId)
JOIN #SUBNETCFILTERTABLE AS f1 ON (f1.IPID = e.ipid)
JOIN #PMSTATUSFILTERTABLE AS f2 ON (f2.VALUEID = e.PMStatus)
WHERE
e.sourceId = @SOURCEID
AND UTCDATE &gt;= @STARTDATE
AND UTCDATE &lt; @ENDDATE
AND EventClass = 'CSMPMonitorLog'

;WITH CSPageEvents AS
(
SELECT
e.CSEVENTID,
e.PAGEURI,
-- Null values should be replaced by 0, to get convergence with Total time after averaging
COALESCE(pe.NetworkTime, 0) AS NetworkTime,
COALESCE(pe.ServerTime, 0) AS ServerTime,
COALESCE(pe.DOMTime, 0) AS DOMTime,
COALESCE(pe.PeripheralTime, 0) AS PeripheralTime,
COALESCE(pe.OnLoadTime, 0) AS OnLoadTime,
pe.TotalTime,
pe.TotalSize
FROM
#CLIENTEVENTS e
JOIN APM.CSPAGEEVENT AS pe (NOLOCK) ON pe.cseventid = e.CSEVENTID AND pe.TotalTime/1000.0 &gt;= @THRESHOLD

),
PageProcessingTime AS
(
SELECT
PageUri,
COUNT(CSEVENTID) AS EventCount,
AVG(NetworkTime)/1000 AS NetworkTime,
AVG(ServerTime)/1000 AS ServerTime,
AVG(DOMTime)/1000 AS DOMTime,
AVG(PeripheralTime)/1000 AS PeripheralTime,
AVG(OnLoadTime)/1000 AS OnLoadTime,
AVG(TotalTime)/1000 AS TotalTime,
AVG(TotalSize)/(1024.0) AS TotalSize
FROM
CSPageEvents
GROUP BY
PageUri
),
NumberedPages AS
(
SELECT
row_number() OVER(ORDER BY EventCount DESC) AS id,
PageUri,
EventCount,
NetworkTime,
ServerTime,
DOMTime,
PeripheralTime,
OnLoadTime,
TotalTime,
TotalSize,
SUM(EventCount) OVER() AS TotalEvents
FROM
PageProcessingTime
)
SELECT
TOP(5)
id,
PageUri,
EventCount,
NetworkTime,
ServerTime,
DOMTime,
PeripheralTime,
OnLoadTime,
TotalTime,
TotalSize,
TotalEvents,
--Get ajax call flag
CASE WHEN EXISTS(
SELECT *
FROM #CLIENTEVENTS c
JOIN CSPageEvent AS pe (NOLOCK) ON pe.cseventid = c.CSEVENTID
JOIN CSAJAX AS csaj (NOLOCK) ON csaj.cseventid = c.CSEVENTID
WHERE d.PageUri = c.PAGEURI
) THEN '*' ELSE ''
END AS Extension
FROM
NumberedPages d
ORDER BY id
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.ApplicationAnalysisExceptionEvents'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.ApplicationAnalysisExceptionEvents AS RETURN 1')
END
GO

/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: ApplicationAnalysisExceptionEvents */
/* USED IN: Application Analysis report for exception events */
/* INPUT PARAMETERS: */
/* @STARTDATE - Start date of the priod */
/* @ENDDATE - End date of the period */
/* @SOURCEID - SourceId */
/* @MACHINEIDS - List of machine Id, separated by comma. Exp: '4,5,6' */
/* @INCLUDESUBNET - List masks, which should be included */
/* @EXCLUDESUBNET - List masks, which should be excluded */
/************************************************************************************/
ALTER PROCEDURE APM.ApplicationAnalysisExceptionEvents
@STARTDATE DATETIME,
@ENDDATE DATETIME,
@SOURCEID NVARCHAR(MAX),
@MACHINEIDS NVARCHAR(MAX),
@INCLUDESUBNET NVARCHAR(MAX),
@EXCLUDESUBNET NVARCHAR(MAX),
@PMSTATUS NVARCHAR(50)
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON

/****************************************************************************************/
/* ASSISTING TEMP TABLES */
/****************************************************************************************/

SELECT
@INCLUDESUBNET = REPLACE(@INCLUDESUBNET, N'*', N'%'),
@EXCLUDESUBNET = REPLACE(@EXCLUDESUBNET, N'*', N'%')

-- Filter table, which contains machine ids
CREATE TABLE #MACHINEFILTERTABLE(
VALUEID INT
)

-- Fill table #MACHINEFILTERTABLE
INSERT
INTO #MACHINEFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@MACHINEIDS, N'') AS p

-- Filter table, which contains PM Statuses of Events
CREATE TABLE #PMSTATUSFILTERTABLE(
VALUEID INT
)

-- Fill table #PMSTATUSFILTERTABLE
INSERT
INTO #PMSTATUSFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@PMSTATUS, N'') AS p

-- Filter table for SubnetC values
CREATE TABLE #SUBNETCFILTERTABLE
(
IPID INT
)

-- Insert into filter id of the SubnetC to increase performence for event table
INSERT INTO #SUBNETCFILTERTABLE
SELECT DISTINCT
ipid
FROM
APM.IP AS ip (NOLOCK)
JOIN APM.GetMultiParameters(CASE WHEN LEN(@INCLUDESUBNET) &gt; 0 THEN @INCLUDESUBNET ELSE N'%' END, N'') AS p1 ON (ip.SubnetC LIKE p1.Value)
LEFT OUTER JOIN APM.GetMultiParameters(CASE WHEN LEN(@EXCLUDESUBNET) &gt; 0 THEN @EXCLUDESUBNET ELSE N'Fake' END, N'') AS p2 ON (ip.SubnetC LIKE p2.Value)
WHERE
--Exclude subnets which have correspondance in @EXCLUDESUBNET parameter
p2.typeId IS NULL

;WITH RequestPCTypeId AS
(
SELECT
PCTypeID
FROM
APM.PCTYPE
WHERE
TYPE = N'\Apps\Monitored Requests'
),
RequestCount AS
(
SELECT
SUM(SUMVALUE) AS RequestCount
FROM
APM.PerfHourly AS ph (NOLOCK)
-- Filter client events by machines
JOIN #MACHINEFILTERTABLE AS f1 ON (ph.MachineId = f1.VALUEID)
JOIN RequestPCTypeId AS pct ON pct.PCTypeID = ph.PCTypeID
WHERE
UTCDATE &gt;= @STARTDATE
AND UTCDATE &lt; @ENDDATE
AND ph.sourceid = @SOURCEID
),
EventDescription AS
(
SELECT
COUNT(CSEVENTID) AS EventCount,
COUNT(DISTINCT CSEVENTGROUPID) AS ProblemCount,
COUNT(CASE WHEN CHARINDEX(N'MSIE', E.BROWSER) &gt; 0 THEN E.CSEVENTID ELSE NULL END) AS IEEventCount,
COUNT(CASE WHEN CHARINDEX(N'Firefox', E.BROWSER) &gt; 0 THEN E.CSEVENTID ELSE NULL END) AS FirefoxEventCount,
DESCRIPTION
FROM
APM.CSEVENT AS e (NOLOCK)
-- Filter client events by machines
JOIN #MACHINEFILTERTABLE AS f1 ON (e.MachineId = f1.VALUEID)
-- Filter client events by subnets
JOIN #SUBNETCFILTERTABLE AS f2 ON (e.ipid = f2.IPID)
JOIN #PMSTATUSFILTERTABLE AS f3 ON (f3.VALUEID = e.PMStatus)
WHERE
e.ClassType = N'exception'
AND UTCDATE &gt; @STARTDATE
AND UTCDATE &lt; @ENDDATE
AND e.sourceid = @SOURCEID
GROUP BY
DESCRIPTION
),
OrderedDataSet AS
(
SELECT
ROW_NUMBER() OVER(ORDER BY E.EventCount DESC) AS id,
EventCount,
ProblemCount,
IEEventCount,
FirefoxEventCount,
Description,
SUM(E.EventCount) OVER() AS TotalEventCount,
SUM(E.ProblemCount) OVER() AS TotalProblemCount
FROM
EventDescription AS e
)
SELECT
TOP(10) E.*, req.RequestCount
FROM
OrderedDataSet AS e
CROSS JOIN RequestCount AS req
ORDER BY
E.ID
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.ApplicationAnalysisOverallStatistics'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.ApplicationAnalysisOverallStatistics AS RETURN 1')
END
GO

/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: ApplicationAnalysisOverallStatistics */
/* USED IN: Application Analysis report */
/* INPUT PARAMETERS: */
/* @STARTDATE - Start date of the priod */
/* @ENDDATE - End date of the period */
/* @SOURCEID - SourceId */
/* @MACHINEIDS - List of machine Id, separated by comma. Exp: '4,5,6' */
/* @INCLUDESUBNET - List masks, which should be included */
/* @EXCLUDESUBNET - List masks, which should be excluded */
/************************************************************************************/
ALTER PROCEDURE APM.ApplicationAnalysisOverallStatistics
@STARTDATE DATETIME,
@ENDDATE DATETIME,
@SOURCEID NVARCHAR(MAX),
@MACHINEIDS NVARCHAR(MAX),
@INCLUDESUBNET NVARCHAR(MAX),
@EXCLUDESUBNET NVARCHAR(MAX),
@PMSTATUS NVARCHAR(50)
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON

/****************************************************************************************/
/* ASSISTING TEMP TABLES */
/****************************************************************************************/
SELECT
@INCLUDESUBNET = REPLACE(@INCLUDESUBNET, N'*', N'%'),
@EXCLUDESUBNET = REPLACE(@EXCLUDESUBNET, N'*', N'%')

-- Filter table, which contains machine ids
CREATE TABLE #MACHINEFILTERTABLE(
VALUEID INT
)

-- Fill table #MACHINEFILTERTABLE
INSERT
INTO #MACHINEFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@MACHINEIDS, N'') AS p

-- Filter table, which contains PM Statuses of Events
CREATE TABLE #PMSTATUSFILTERTABLE(
VALUEID INT
)

-- Fill table #PMSTATUSFILTERTABLE
INSERT
INTO #PMSTATUSFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@PMSTATUS, N'') AS p

-- Filter table for SubnetC values
CREATE TABLE #SUBNETCFILTERTABLE
(
IPID INT
)

-- Insert into filter id of the SubnetC to increase performence for event table
INSERT INTO #SUBNETCFILTERTABLE
SELECT DISTINCT
ipid
FROM
APM.IP AS ip (NOLOCK)
JOIN APM.GetMultiParameters(CASE WHEN LEN(@INCLUDESUBNET) &gt; 0 THEN @INCLUDESUBNET ELSE N'%' END, N'') AS p1 ON (ip.SubnetC LIKE p1.Value)
LEFT OUTER JOIN APM.GetMultiParameters(CASE WHEN LEN(@EXCLUDESUBNET) &gt; 0 THEN @EXCLUDESUBNET ELSE N'Fake' END, N'') AS p2 ON (ip.SubnetC LIKE p2.Value)
WHERE
--Exclude subnets which have correspondance in @EXCLUDESUBNET parameter
p2.typeId IS NULL

CREATE TABLE #CLIENTEVENTS
(
CSEVENTID INT,
CSEVENTGROUPID INT,
CLASSTYPE NVARCHAR(50) COLLATE DATABASE_DEFAULT
)

INSERT INTO #CLIENTEVENTS
SELECT
e.cseventid,
e.csEventGroupId,
e.ClassType
FROM
APM.CSEVENT AS e (NOLOCK)
-- Filter client events by machines
JOIN #MACHINEFILTERTABLE AS f1 ON (e.MachineId = f1.VALUEID)
-- Filter client events by subnets
JOIN #SUBNETCFILTERTABLE AS f2 ON (e.ipid = f2.IPID)
JOIN #PMSTATUSFILTERTABLE AS f3 ON (f3.VALUEID = e.PMStatus)
WHERE
e.sourceid = @SOURCEID
AND UTCDATE &gt; @STARTDATE
AND UTCDATE &lt; @ENDDATE

;WITH RequestPCTypeId AS
(
SELECT
PCTypeID
FROM
APM.PCTYPE
WHERE
TYPE = N'\Apps\Monitored Requests'
),
RequestCount AS
(
SELECT
SUM(SUMVALUE) AS RequestCount
FROM
APM.PerfHourly AS ph
-- Filter client events by machines
JOIN #MACHINEFILTERTABLE AS f1 ON (ph.MachineId = f1.VALUEID)
JOIN RequestPCTypeId AS pct ON pct.PCTypeID = ph.PCTypeID
WHERE
ph.sourceid = @SOURCEID
AND UTCDATE &gt; @STARTDATE
AND UTCDATE &lt; @ENDDATE
),
AJAXEvents AS
(
SELECT
AVG(ajax.REQUESTSIZE + ajax.ResponseSize) AS AjaxCallSize,
AVG(ajax.TotalTime) AS AjaxCallDuration,
MAX(ajax.REQUESTSIZE + ajax.ResponseSize) AS MaxAjaxCallSize,
MAX(ajax.TotalTime) AS MaxAjaxCallDuration,
COUNT(ajax.CSEventId) AS AjaxCallCount
FROM
APM.CSAJAX AS ajax (NOLOCK)
JOIN #CLIENTEVENTS AS e ON ajax.CSEventId = e.CSEVENTID
WHERE
e.CLASSTYPE = N'performance'
),
ExceptionEvents AS
(
SELECT
COUNT(CSEVENTID) AS EventCount,
COUNT(CSEVENTGROUPID) AS ProblemCount
FROM
#CLIENTEVENTS AS e
WHERE
e.CLASSTYPE = N'exception'
),
PerformanceEvents AS
(
SELECT
COUNT(CSEVENTID) AS EventCount,
COUNT(CSEVENTGROUPID) AS ProblemCount
FROM
#CLIENTEVENTS AS e
WHERE
e.CLASSTYPE = N'performance'
)
SELECT
e.EventCount AS ExceptionEventsCount,
e.ProblemCount AS ExceptionProblemCount,
perf.EventCount AS PerformanceEventsCount,
perf.ProblemCount AS PerformanceProblemCount,
ajax.AjaxCallSize/1024.0 AS AjaxCallSize,
ajax.AjaxCallDuration/1000.0 AS AjaxCallDuration,
ajax.MaxAjaxCallSize/1024.0 AS MaxAjaxCallSize,
ajax.MaxAjaxCallDuration/1000.0 AS MaxAjaxCallDuration,
ajax.AjaxCallCount,
req.RequestCount
FROM
ExceptionEvents AS e
CROSS JOIN PerformanceEvents AS perf
CROSS JOIN RequestCount AS req
CROSS JOIN AJAXEvents AS ajax
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.SummaryPerformanceAnalysisReportTopJS'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.SummaryPerformanceAnalysisReportTopJS AS RETURN 1')
END
GO

/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: SummaryPerformanceAnalysisReportTopJS */
/* USED IN: Summary Performance Analysis Report */
/* INPUT PARAMETERS: */
/* @STARTDATE - Start date of the priod */
/* @ENDDATE - End date of the period */
/* @SOURCE - source Id */
/* @MACHINEIDS - List of machine Id, separated by comma. Exp: '4,5,6' */
/* @INCLUDESUBNET - Subnet masks list, which should be included */
/* @EXCLUDESUBNET - Subnet mask list, which should be excluded */
/* @THRESHOLD - Event threshold */
/************************************************************************************/

ALTER PROCEDURE APM.SummaryPerformanceAnalysisReportTopJS
@STARTDATE DATETIME,
@ENDDATE DATETIME,
@SOURCE INT,
@MACHINEIDS NVARCHAR(MAX),
@INCLUDESUBNET NVARCHAR(MAX),
@EXCLUDESUBNET NVARCHAR(MAX),
@THRESHOLD INT,
@PMSTATUS NVARCHAR(50)
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON

/****************************************************************************************/
/* ASSISTING TEMP TABLES */
/****************************************************************************************/

SELECT
@INCLUDESUBNET = REPLACE(@INCLUDESUBNET, N'*', N'%'),
@EXCLUDESUBNET = REPLACE(@EXCLUDESUBNET, N'*', N'%')

-- Filter table, which contains msource ids
CREATE TABLE #SOURCEFILTERTABLE(
VALUEID INT
)

-- Fill table #SOURCEMACHINEFILTERTABLE
INSERT
INTO #SOURCEFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@MACHINEIDS, N'') AS p

-- Filter table for SubnetC values
CREATE TABLE #SUBNETCFILTERTABLE
(
IPID INT
)

-- Insert into filter id of the SubnetC to increase performence for event table
INSERT INTO #SUBNETCFILTERTABLE
SELECT DISTINCT
ipid
FROM
APM.IP AS ip (NOLOCK)
JOIN APM.GetMultiParameters(CASE WHEN LEN(@INCLUDESUBNET) &gt; 0 THEN @INCLUDESUBNET ELSE N'%' END, N'') AS p1 ON (ip.SubnetC LIKE p1.Value)
LEFT OUTER JOIN APM.GetMultiParameters(CASE WHEN LEN(@EXCLUDESUBNET) &gt; 0 THEN @EXCLUDESUBNET ELSE N'Fake' END, N'') AS p2 ON (ip.SubnetC LIKE p2.Value)
WHERE
--Exclude subnets which have correspondance in @EXCLUDESUBNET parameter
p2.typeId IS NULL


-- Filter table, which contains PM Statuses of Events
CREATE TABLE #PMSTATUSFILTERTABLE(
VALUEID INT
)

-- Fill table #PMSTATUSFILTERTABLE
INSERT
INTO #PMSTATUSFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@PMSTATUS, N'') AS p

;WITH CSAjaxPageEvents AS
(
SELECT
e.CSEventID,
e.pageUri,
-- This name will be used only for Asynch Ajax Event, and for this events here will be only one row
MAX(ajax.uri) AS ActionName,
SUM(ajax.TotalTime) AS AJAXCallProcessingTime,
SUM(ajax.NetworkTime) AS NetworkTime,
SUM(ajax.ServerTime) AS ServerTime,
SUM(ajax.REQUESTSIZE) AS RequestSize,
SUM(ajax.ResponseSize) AS ResponseSize
FROM
APM.CSEVENT AS e (NOLOCK)
JOIN #SOURCEFILTERTABLE AS f1 ON (f1.VALUEID = e.MachineId)
JOIN #SUBNETCFILTERTABLE AS f2 ON e.ipid = f2.IPID
JOIN #PMSTATUSFILTERTABLE AS f3 ON (f3.VALUEID = e.PMStatus)
LEFT OUTER JOIN APM.CSAjax (NOLOCK) AS ajax ON ajax.cseventid = e.cseventid
WHERE
e.sourceId = @SOURCE
AND e.UTCDate &gt;= @STARTDATE
AND e.UTCDate &lt; @ENDDATE
AND e.EventClass &lt;&gt; N'CSMPMonitorLog'
GROUP BY
e.CSEventID,
e.pageUri
),
AJAXEventSummary AS
(
SELECT
e.CSEventID,
e.pageUri,
COALESCE(js.Action, e.ActionName) AS JSActionName,
COALESCE(js.TotalTime, e.AJAXCallProcessingTime) AS TotalTime,
COALESCE(js.TotalTime - COALESCE(e.AJAXCallProcessingTime, 0), asyncAjax.HandlerTime) AS ClientTime,
COALESCE(e.NetworkTime, 0) AS NetworkTime,
COALESCE(e.ServerTime, 0) AS ServerTime,
e.REQUESTSIZE,
e.ResponseSize
FROM
CSAjaxPageEvents AS e
LEFT OUTER JOIN APM.CSJScriptEvent AS js (NOLOCK) ON js.cseventid = e.cseventid
LEFT OUTER JOIN APM.CSAsyncAjax AS asyncAjax (NOLOCK) ON asyncAjax.cseventid = e.cseventid
WHERE
COALESCE(js.TotalTime, e.AJAXCallProcessingTime)/1000.0 &gt;= @THRESHOLD
),
AjaxPage AS
(
SELECT
JSActionName,
pageUri,
COUNT(CSEventID) AS EventCount,
AVG(ClientTime)/1000 AS ClientTime,
AVG(NetworkTime)/1000 AS NetworkTime,
AVG(ServerTime)/1000 AS ServerTime,
AVG(TotalTime)/1000 AS AJAXTotalTime,
AVG(RequestSize)/(1024.0) AS RequestSize,
AVG(ResponseSize)/(1024.0) AS ResponseSize
FROM
AJAXEventSummary
GROUP BY
JSActionName,pageUri
),
OrderedActions AS
(
SELECT
ROW_NUMBER() OVER(ORDER BY EventCount DESC) AS id,
EventCount,
JSActionName,
pageUri,
ClientTime,
NetworkTime,
ServerTime,
AJAXTotalTime AS TotalTime,
RequestSize + ResponseSize AS AJAXCallSize,
SUM(EventCount) OVER() AS TotalEvents
FROM
AjaxPage
)
SELECT TOP(5)
*
FROM
OrderedActions
ORDER BY
id
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.ApplicationActivityBreakdownByMonthDate'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.ApplicationActivityBreakdownByMonthDate AS RETURN 1')
END
GO

/****************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: ApplicationActivityBreakdownByMonthDate */
/* USED IN: Application Status Report, Application Activity */
/* DESCRIPTION: This SP is used in report above in case, when grouping by month date */
/* specified */
/* INPUT PARAMETERS: */
/* @SOURCEIDS - List of the source id, separated by comma. Exp: '1,2,3' */
/* @COMPUTERIDS - List of the computer id, separated by comma. Exp: '1,2,3' */
/* @ENDDATE - End date of the period in Client time zone */
/* @PERIOD - Period type(Day, Week or Month). */
/* - Use for the Start Date calculate of the period */
/* @AVERAGEINTERVAL- This value specifies interval, for which average values will */
/* be calculated. Possible values: 1(1 month), 2(2 month), */
/* 3(3 month), 6(6 month), 17 (7 day) */
/* @GROUPBY - Specifies result gouping type. Possible values: */
/* Hour - Group by hours. Rersult set will contain 24 rows */
/* corresponding to 24 hours. Date field - 0-23, Hour field - 0 */
/* WeekDay - Group by week days. For this grouping type extra grouping */
/* is applied - by hours. So result data set contains 7*24 rows. */
/* Date field values - 1-7, Hour fields - 0-23 */
/* Month - Group by Month. For this grouping type extra grouping */
/* is applied - by months. So result data set contains 12*24 rows. */
/* and Hour field - 0-23 */
/* @TRESHOLD - Event duration treshold */
/* @PROBLEM - Event problem type (all, critical) */
/* @TIMEZONE - correlate parameter (timezone by min) */
/* - for the End Date calculate */
/****************************************************************************************/
ALTER PROCEDURE APM.ApplicationActivityBreakdownByMonthDate
@SOURCEIDS NVARCHAR(MAX),
@COMPUTERIDS NVARCHAR(MAX),
@ENDDATE DATETIME,
@TIMEZONE INT,
@PERIOD INT,
@AVERAGEINTERVAL INT,
@GROUPBY NVARCHAR(10),
@THRESHOLD INT,
@PROBLEM NVARCHAR(10),
@PMSTATUS NVARCHAR(50)
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON;

/************************************************************************************/
/* Prepare auxiliary variables for the further calculation */
/************************************************************************************/

--Used for counting average value for last three months
DECLARE @PERIODDAYSCOUNT int
SET @PERIODDAYSCOUNT = 31

SET @ENDDATE = DATEADD(minute, -@TIMEZONE, @ENDDATE)

DECLARE @STARTDATE DateTime
SET @STARTDATE = DATEADD(d, -@PERIODDAYSCOUNT, @ENDDATE)

DECLARE @LASTPERIODSTARTDATE DateTime
SET @LASTPERIODSTARTDATE = DATEADD(d, -@PERIODDAYSCOUNT, @STARTDATE)

DECLARE @AVERAGEPERIODSTARTDATE DateTime
SET @AVERAGEPERIODSTARTDATE = (CASE
WHEN @AVERAGEINTERVAL &lt; 10 THEN DATEADD(month, -@AVERAGEINTERVAL, @STARTDATE)
ELSE DATEADD(day, -(@AVERAGEINTERVAL-10), @STARTDATE)
END)

DECLARE @PROCESSORCOUNTERID INT
SELECT @PROCESSORCOUNTERID = PCtypeId FROM APM.PCType (NOLOCK) WHERE type = N'\Process\% Processor Time'

DECLARE @MEMORYCOUNTERID INT
SELECT @MEMORYCOUNTERID = PCtypeId FROM APM.PCType (NOLOCK) WHERE type = N'\Process\Private Bytes'

DECLARE @IOCOUNTERID INT
SELECT @IOCOUNTERID = PCtypeId FROM APM.PCType (NOLOCK) WHERE type = N'\Process\IO Data Bytes/sec'

DECLARE @MONITOREDREQUESTCOUNTERID INT
SELECT @MONITOREDREQUESTCOUNTERID = PCtypeId FROM APM.PCType (NOLOCK) WHERE type = N'\Apps\Monitored Requests'

DECLARE @REQUESTTIMECOUNTERID INT
SELECT @REQUESTTIMECOUNTERID = PCtypeId FROM APM.PCType (NOLOCK) WHERE type = N'\Apps\Avg. Request Time'

/************************************************************************************/
/* ASSISTING TEMP TABLES */
/************************************************************************************/
-- Filter table, which contains machine ids and source ids
-- typeid defines filter type - 1 for source and 2 for machine
-- valueId filter value - source id and machine id
CREATE TABLE #SOURCEMACHINEFILTERTABLE(
TYPEID INT,
VALUEID INT
)

-- Fill table #SOURCEMACHINEFILTERTABLE
INSERT
INTO #SOURCEMACHINEFILTERTABLE
SELECT
p.typeId AS TYPEID,
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@SOURCEIDS, @COMPUTERIDS) AS p

-- Filter table, which contains PM Statuses of Events
CREATE TABLE #PMSTATUSFILTERTABLE(
VALUEID INT
)

-- Fill table #PMSTATUSFILTERTABLE
INSERT
INTO #PMSTATUSFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@PMSTATUS, N'') AS p

-- To form application pool with all sources run in it, it is need to get all sources and its process
CREATE TABLE #PROCESSFORSOURCE
(
SOURCEID INT,
PCPROCESSID INT,
MACHINEID INT,
EXTRAINFO NVARCHAR(255) COLLATE DATABASE_DEFAULT,
PROCESS NVARCHAR(255) COLLATE DATABASE_DEFAULT
)

INSERT INTO #PROCESSFORSOURCE
SELECT
ph.SourceId,
ph.PCProcessId,
ph.MachineId,
COALESCE(p.Extrainfo, N'') AS EXTRAINFO,
--Select process name till # symbol (w3wp#1 -&gt; w3wp, w3wp -&gt; w3wp)
APM.RemoveProcessIdFromName(p.Process) AS Process
FROM
(
SELECT DISTINCT
ph.SourceId,
ph.pcprocessId,
ph.MachineId
FROM
APM.PerfHourly AS ph (NOLOCK)
WHERE
ph.pcprocessId IS NOT NULL
AND ph.UTCDate &gt;= @STARTDATE
AND ph.UTCDate &lt; @ENDDATE
) AS ph
JOIN APM.PCProcess AS p (NOLOCK) ON p.pcprocessId = ph.pcprocessId
JOIN #SOURCEMACHINEFILTERTABLE AS f ON (f.TYPEID = 2 AND ph.MachineId = f.VALUEID)


-- Report frame. It contains all sources, for which values sould be selected,
-- and dates for the specified period (StartDate : EndDate)
;WITH SourcesDates AS
(
SELECT
VALUEID AS sourceid,
s.source AS source,
-- Select 31 day from end date in ClientTime zone, without hours
CONVERT(NVARCHAR, DATEADD(d, -d.n, DATEADD(minute, @TIMEZONE, @ENDDATE)), 112) AS ClientDate
FROM
#SOURCEMACHINEFILTERTABLE AS source
JOIN APM.source (NOLOCK) AS s ON s.sourceid = source.VALUEID
CROSS JOIN APM.fn_nums(31) AS d
WHERE
source.TYPEID = 1
),
AppPoolInfo AS
(
SELECT
c.SOURCEID,
c.EXTRAINFO,
c.PROCESS,
-- all source names which have the same process name as passed in @SOURCEIDS
(SELECT A.source AS [data()]
FROM
(
SELECT DISTINCT
N'''' + s.source + N'''' + N',' AS source
FROM
#PROCESSFORSOURCE AS c1
JOIN APM.Source AS s ON c1.SOURCEID = s.SourceId
WHERE
c1.EXTRAINFO = c.EXTRAINFO
AND c1.PROCESS = c.PROCESS
AND c1.MACHINEID = c.MACHINEID
) AS A
FOR XML PATH ('')
) AS AppPoolSources
FROM
#PROCESSFORSOURCE AS c
JOIN #SOURCEMACHINEFILTERTABLE AS f ON (f.TYPEID = 1 AND f.VALUEID = c.SOURCEID)
GROUP BY
c.SOURCEID,
c.MACHINEID,
c.EXTRAINFO,
c.PROCESS
),
--Add Pool name in-front of source list, if it is executable application, then app pool countains source name
PrepareAppPoolInfo AS (
SELECT DISTINCT
CASE
WHEN COALESCE(info.ExtraInfo,'') = '' THEN CASE info.AppPoolSources WHEN '' THEN '' ELSE LEFT(info.AppPoolSources, LEN(info.AppPoolSources)-1) END
ELSE info.ExtraInfo + CASE info.AppPoolSources WHEN '' THEN '' ELSE ' (' + LEFT(info.AppPoolSources, LEN(info.AppPoolSources) - 1) + ')' END
END AppPool,
info.SourceId,
info.ExtraInfo
FROM
AppPoolInfo AS info
),
-- Forms application pool list for each source
-- Format: AppPool1 ('Source1', 'Source2', Source3), AppPool2 ('Source1', 'Source4')
SourceAppPools AS (
SELECT
s.SourceId,
s.Source,
COALESCE((SELECT a.AppPool AS [data()]
FROM
(
SELECT DISTINCT
info.AppPool + N',' AS AppPool
FROM
PrepareAppPoolInfo as info
WHERE
info.Sourceid = s.Sourceid
) AS A
FOR XML PATH ('')
),s.Source + '-') AS AppPoolInfo
FROM
APM.Source AS s
JOIN #SOURCEMACHINEFILTERTABLE AS f ON (f.TYPEID = 1 AND f.VALUEID = s.SourceId)
),
--Prepares and filters events for further manipulations
ActivityBreakdown_EventsFiltered AS
(
SELECT
e.sourceid,
e.eventid,
e.utceventdate AS eventdate,
-- Event Date in Client Timezone without hours
CONVERT(NVARCHAR, DATEADD(minute, @TIMEZONE, e.utceventdate), 112) AS ClientDate,
--hour is taken as DateDifference in day between 05/04/2009 9:00AM and 05/03/2009 9:00PM is one day,
--despite in case of @PERIOD = 'Day' it can be interpretated as one day (if 05/04/2009 9:00AM is end date), so difference should be taken as 0
ABS(DATEDIFF(hour, e.utceventdate, @ENDDATE)) / (@PERIODDAYSCOUNT*24) AS PeriodId,
e.eventgroupid,
db.ADDRESS AS SeViewerAddress
FROM
APM.Event AS e
JOIN APM.SeViewerDB AS db ON e.seviewerdbid = db.seviewerdbid
JOIN #SOURCEMACHINEFILTERTABLE AS f1 ON (f1.VALUEID = e.sourceid and f1.TYPEID = 1)
JOIN #SOURCEMACHINEFILTERTABLE AS f2 ON (f2.VALUEID = e.machineid and f2.TYPEID = 2)
JOIN #PMSTATUSFILTERTABLE AS f3 ON (f3.VALUEID = e.PMStatus)
WHERE
((e.EventClassType = N'Performance' AND e.eventduration / 1000000.0 &gt;= @THRESHOLD)
OR e.EventClassType = N'exception')
AND (e.category LIKE @PROBLEM OR e.category IS NULL)
AND e.utceventdate &gt;= @AVERAGEPERIODSTARTDATE
AND e.utceventdate &lt; @ENDDATE
AND (e.HeavyLight &lt;&gt; 0 OR e.HeavyLight IS NULL)

),
/************************************************************************************/
/* Base pcounter queries */
/************************************************************************************/
-- Calculate resource utilization by Source in one hour.
-- Aggregation between instances should be done here (for cases when one source run in several process in one hour)
SourceHourlyResourceUtilization AS
(
SELECT
ph.MachineId,
ph.SourceId,
-- PerfHourly date in client time zone without hours
CONVERT(NVARCHAR, DATEADD(minute, @TIMEZONE ,ph.UTCDate), 112) AS ClientDate,
ph.PCTypeId AS Type,

---------- Pivot instance count by period type -----------
(CASE
WHEN ph.UtcDate &gt;= @LASTPERIODSTARTDATE AND ph.UtcDate &lt; @STARTDATE
THEN SUM(ph.SampleCount)*1.0/MAX(ph.PackageCounter)
END) AS LastInstanceCount,
(CASE
WHEN ph.UtcDate &gt;= @STARTDATE AND ph.UtcDate &lt; @ENDDATE
THEN SUM(ph.SampleCount)*1.0/MAX(ph.PackageCounter)
END) AS CurInstanceCount,
(CASE
WHEN ph.utcdate &gt;= @AVERAGEPERIODSTARTDATE AND ph.utcdate &lt; @STARTDATE
THEN SUM(ph.SampleCount)*1.0/MAX(ph.PackageCounter)
END) AS AvgInstanceCount,

---------- Pivot resource value by period type -----------
(CASE
WHEN ph.UtcDate &gt;= @LASTPERIODSTARTDATE AND ph.UtcDate &lt; @STARTDATE THEN SUM(SumValue)/SUM(SampleCount)
END) AS LastValue,
(CASE
WHEN ph.UtcDate &gt;= @STARTDATE AND ph.UtcDate &lt; @ENDDATE THEN SUM(SumValue)/SUM(SampleCount)
END) AS CurValue,
(CASE
WHEN ph.utcdate &gt;= @AVERAGEPERIODSTARTDATE AND ph.utcdate &lt; @STARTDATE THEN SUM(SumValue)/SUM(SampleCount)
END) AS AvgValue,
ABS(DATEDIFF(hour, ph.UTCDate, @ENDDATE)) / (@PERIODDAYSCOUNT*24) AS PeriodId
FROM
APM.PerfHourly AS ph (NOLOCK)
--Join with #SOURCEMACHINEFILTERTABLE with typeid = 1 provides filtering perfHourly by sourceid
JOIN #SOURCEMACHINEFILTERTABLE AS f1 ON (f1.TYPEID = 1 AND f1.VALUEID = ph.SourceId)
--Join with #SOURCEMACHINEFILTERTABLE with typeid = 2 provides filtering perfHourly by machineid
JOIN #SOURCEMACHINEFILTERTABLE AS f2 ON (f2.TYPEID = 2 AND f2.VALUEID = ph.MachineId)
WHERE
ph.UTCDate &gt;= @AVERAGEPERIODSTARTDATE
AND ph.UTCDate &lt; @ENDDATE
AND ph.PCTypeId IN (@PROCESSORCOUNTERID, @IOCOUNTERID, @MEMORYCOUNTERID)
GROUP BY
ph.MachineId,
ph.SourceId,
ph.UTCDate,
ph.PCTypeId
),
-- Bring ClientDate to current period, as in result data set, data only for current period are shown
-- (all other should be shown relative to current period)
SourceHourlyResourceUtilizationByCurrentPeriod AS
(
SELECT
ph.MachineId,
ph.SourceId,
-- PeriodId is 0 for the current period, 1 for last and 1..n for average
-- this manipulation should bring Client date to current period
DATEADD(day, ph.PeriodId*31, ClientDate) AS ClientDate,
ph.Type,
ph.LastInstanceCount,
ph.CurInstanceCount,
ph.AvgInstanceCount,
ph.LastValue,
ph.CurValue,
ph.AvgValue,
ph.PeriodId
FROM
SourceHourlyResourceUtilization AS ph
),
--Calculate average source resource utilization for each resource type
--and for specified grouping period and date
ApplicationResourceUtilizationByMachines AS
(
SELECT
ph.MachineId,
ph.SourceId,
ph.PeriodId,
ph.ClientDate,
-- Instance count should be same for different resource types in one hour for one process
-- and averaging them won't make any difference but allow to avoid one aggregation step
AVG(ph.CurInstanceCount) AS CurInstanceCount,
AVG(ph.LastInstanceCount) AS LastInstanceCount,
AVG(ph.AvgInstanceCount) AS AvgInstanceCount,

---------- Pivot resource by counter type -----------

----------- 'Process% Processor Time' counter -------------------
AVG(CASE WHEN ph.type = @PROCESSORCOUNTERID THEN ph.CurValue END) AS CurCPUSum,
AVG(CASE WHEN ph.type = @PROCESSORCOUNTERID THEN ph.LastValue END) AS LastCPUSum,
AVG(CASE WHEN ph.type = @PROCESSORCOUNTERID THEN ph.AvgValue END) AS AvgCPUSum,

----------- 'ProcessPrivate Bytes' counter -------------------
AVG(CASE WHEN ph.type = @MEMORYCOUNTERID THEN ph.CurValue END) AS CurMemSum,
AVG(CASE WHEN ph.type = @MEMORYCOUNTERID THEN ph.LastValue END) AS LastMemSum,
AVG(CASE WHEN ph.type = @MEMORYCOUNTERID THEN ph.AvgValue END) AS AvgMemSum,

----------- 'ProcessIO Data Bytes/sec' counter -------------------
AVG(CASE WHEN ph.type = @IOCOUNTERID THEN ph.CurValue END) AS CurIOSum,
AVG(CASE WHEN ph.type = @IOCOUNTERID THEN ph.LastValue END) AS LastIOSum,
AVG(CASE WHEN ph.type = @IOCOUNTERID THEN ph.AvgValue END) AS AvgIOSum
FROM
SourceHourlyResourceUtilizationByCurrentPeriod AS ph
GROUP BY
ph.MachineId,
ph.SourceId,
ph.PeriodId,
ph.ClientDate
),
-- Count Monitored Requests and Avg. Request Timefor Application on each machine
-- as source can run on different machines with same process name and app pool, but different sources set,
-- it is important to group by machine to, to avoid calculation of requests from the other app pool
-- Summarize request count in each period (PeriodId differs only for AvgValue)
ApplicationNetAppCountersByMachinePrepare AS
(
SELECT
ph.MachineId,
ph.SourceId,
CONVERT(NVARCHAR, DATEADD(minute, @TIMEZONE, ph.UTCDate), 112) AS ClientDate,
----------------- Pivot Monitor Request Counter by period ------------------
CASE WHEN ph.UtcDate &gt;= @LASTPERIODSTARTDATE AND ph.UtcDate &lt; @STARTDATE
THEN SUM(CASE WHEN ph.PCTypeId = @MONITOREDREQUESTCOUNTERID THEN ph.SumValue END)
END AS LastMonRequest,
CASE WHEN ph.UtcDate &gt;= @STARTDATE AND ph.UtcDate &lt; @ENDDATE
THEN SUM(CASE WHEN ph.PCTypeId = @MONITOREDREQUESTCOUNTERID THEN ph.SumValue END)
END AS CurMonRequest,
CASE WHEN ph.utcdate &gt;= @AVERAGEPERIODSTARTDATE AND ph.utcdate &lt; @STARTDATE
THEN SUM(CASE WHEN ph.PCTypeId = @MONITOREDREQUESTCOUNTERID THEN ph.SumValue END)
END AS AvgMonRequest,

----------------- Pivot Avg. Request Time Counter by period ------------------
CASE WHEN ph.UtcDate &gt;= @LASTPERIODSTARTDATE AND ph.UtcDate &lt; @STARTDATE
THEN AVG(CASE WHEN ph.PCTypeId = @REQUESTTIMECOUNTERID THEN ph.SumValue / ph.SampleCount END)
END AS LastAvgReqTime,
CASE WHEN ph.UtcDate &gt;= @STARTDATE AND ph.UtcDate &lt; @ENDDATE
THEN AVG(CASE WHEN ph.PCTypeId = @REQUESTTIMECOUNTERID THEN ph.SumValue / ph.SampleCount END)
END AS CurAvgReqTime,
CASE WHEN ph.utcdate &gt;= @AVERAGEPERIODSTARTDATE AND ph.utcdate &lt; @STARTDATE
THEN AVG(CASE WHEN ph.PCTypeId = @REQUESTTIMECOUNTERID THEN ph.SumValue / ph.SampleCount END)
END AS AvgReqTime,

ABS(DATEDIFF(hour, ph.UTCDate, @ENDDATE)) / (@PERIODDAYSCOUNT*24) AS PeriodId
FROM
apm.PerfHourly AS ph (NOLOCK)
--Join with #SOURCEMACHINEFILTERTABLE provides filtering perfHourly by sourceid
JOIN #SOURCEMACHINEFILTERTABLE AS f1 ON (f1.TYPEID = 1 AND ph.SourceId = f1.VALUEID)
--Join with #SOURCEMACHINEFILTERTABLE provides filtering perfHourly by machineid
JOIN #SOURCEMACHINEFILTERTABLE AS f2 ON (f2.TYPEID = 2 AND f2.VALUEID = ph.MachineId)
WHERE
ph.UTCDate &gt;= @AVERAGEPERIODSTARTDATE
AND ph.UTCDate &lt; @ENDDATE
AND ph.PCTypeID IN (@REQUESTTIMECOUNTERID, @MONITOREDREQUESTCOUNTERID)
GROUP BY
ph.MachineId,
ph.SourceId,
ph.UTCDate
),
-- Bring ClientDate to current period, as in result data set, data only for current period are shown
-- (all other should be shown relative to current period)
ApplicationNetAppCountersByCurrentPeriod AS
(
SELECT
ph.MachineId,
ph.SourceId,
-- PeriodId is 0 for the current period, 1 for last and 1..n for average
-- this manipulation should bring Client date to current period
DATEADD(day, ph.PeriodId*31, ClientDate) AS ClientDate,
ph.LastMonRequest,
ph.CurMonRequest,
ph.AvgMonRequest,
ph.LastAvgReqTime,
ph.CurAvgReqTime,
ph.AvgReqTime,
ph.PeriodId
FROM
ApplicationNetAppCountersByMachinePrepare AS ph
),
--Calculate average request time and sum request count for specified grouping period and date
ApplicationNetAppCountersByMachine AS
(
SELECT
ph.MachineId,
ph.SourceId,
ph.PeriodId,
ph.ClientDate,
SUM(ph.LastMonRequest) AS LastMonRequest,
SUM(ph.CurMonRequest) AS CurMonRequest,
SUM(ph.AvgMonRequest) AS AvgMonRequest,
AVG(ph.LastAvgReqTime) AS LastAvgReqTime,
AVG(ph.CurAvgReqTime) AS CurAvgReqTime,
AVG(ph.AvgReqTime) AS AvgReqTime
FROM
ApplicationNetAppCountersByCurrentPeriod ph
GROUP BY
ph.MachineId,
ph.SourceId,
ph.PeriodId,
ph.ClientDate
),
-- Union .NET counters and process counters for period Id. Period Id differs only for average(last three months) values, so grouping only for them
PCountersGroupedByMachineId AS (
SELECT
pc.machineId,
pc.SourceId,
pc.ClientDate,

MAX(netApp.CurMonRequest) AS CurReqCount,
MAX(netApp.LastMonRequest) AS LastReqCount,
AVG(netApp.AvgMonRequest) AS AvgReqCount,

MAX(netApp.CurAvgReqTime) AS CurAvgReqTime,
MAX(netApp.LastAvgReqTime) AS LastAvgReqTime,
AVG(netApp.AvgReqTime) AS AvgReqTime,

MAX(pc.CurCPUSum) AS CurCPUSum,
MAX(pc.LastCPUSum) AS LastCPUSum,
AVG(pc.AvgCPUSum) AS AvgCPUSum,
MAX(pc.CurMemSum) AS CurMemSum,
MAX(pc.LastMemSum) AS LastMemSum,
AVG(pc.AvgMemSum) AS AvgMemSum,
MAX(pc.CurIOSum) AS CurIOSum,
MAX(pc.LastIOSum) AS LastIOSum,
AVG(pc.AvgIOSum) AS AvgIOSum
FROM ApplicationResourceUtilizationByMachines pc
LEFT JOIN ApplicationNetAppCountersByMachine AS netApp ON netApp.MachineId = pc.MachineId
AND netApp.SourceId = pc.SourceId AND netApp.PeriodId = netApp.PeriodId
AND netApp.ClientDate = pc.ClientDate
GROUP BY
pc.machineId,
pc.SourceId,
pc.ClientDate
),
-- Calculate average source resource utilization between machines
ActivePreparePCounters AS (
SELECT
pc.SourceId,
-- Convert date to appropriate format to provide correct comparison
pc.ClientDate,
SUM(CurReqCount) AS CurReqCount,
SUM(LastReqCount) AS LastReqCount,
SUM(AvgReqCount) AS AvgReqCount,
AVG(CurAvgReqTime) AS CurAvgReqTime,
AVG(LastAvgReqTime) AS LastAvgReqTime,
AVG(AvgReqTime) AS AvgReqTime,
AVG(CurCPUSum / COALESCE(m.CPUCount, 1)) AS CurCPUSum,
AVG(LastCPUSum / COALESCE(m.CPUCount, 1) ) AS LastCPUSum,
AVG(AvgCPUSum / COALESCE(m.CPUCount, 1)) AS AvgCPUSum,


AVG(CurMemSum) AS CurMemSum,
AVG(LastMemSum) AS LastMemSum,
AVG(AvgMemSum) AS AvgMemSum,
AVG(CurIOSum) AS CurIOSum,
AVG(LastIOSum) AS LastIOSum,
AVG(AvgIOSum) AS AvgIOSum
FROM
PCountersGroupedByMachineId AS pc
JOIN apm.Machine AS m ON m.MachineId = pc.MachineId
GROUP BY
pc.SourceId,
pc.ClientDate
),
-- Count events for the current, last and average period.
-- PeriodId is 0 for Current period, 1 for last period, and 1..n for average period
PrepareEventsAvg AS
(
SELECT
e.sourceid AS sourceid,
-- PeriodId is 0 for the current period, 1 for last and 1..n for average
-- this manipulation should bring Client date to current period
DATEADD(day, e.PeriodId*31, e.ClientDate) AS ClientDate,
e.PeriodId,
MAX(E.SeViewerAddress) AS SeViewerAddress,
COUNT(CASE WHEN e.eventdate &gt;= @STARTDATE AND e.eventdate &lt; @ENDDATE THEN eventid END) AS CurrentEventsCount,
COUNT(CASE WHEN e.eventdate &gt;= @LASTPERIODSTARTDATE AND e.eventdate &lt; @STARTDATE THEN eventid END) AS LasEventsCount,
COUNT(CASE WHEN E.eventdate &gt;= @AVERAGEPERIODSTARTDATE AND E.eventdate &lt; @STARTDATE THEN eventid END) AS AvgEventsCount
FROM
ActivityBreakdown_EventsFiltered AS e
GROUP BY
e.sourceid,
e.PeriodId,
e.ClientDate
),
Events AS
(
SELECT
e.sourceid AS sourceid,
-- Convert date to appropriate format to provide correct comparison
e.ClientDate,
MAX(E.SeViewerAddress) AS SeViewerAddress,
--PeriodId differs only for average, so for current and last period it doesn't matter which agg function is taken
MAX(CurrentEventsCount) AS CurrentEventsCount,
MAX(LasEventsCount) AS LasEventsCount,
--Average counting is not included current period
AVG(AvgEventsCount) AS AvgEventsCount
FROM
PrepareEventsAvg AS e
GROUP BY
sourceid,
e.ClientDate
),
-- Check that CPU count is defined for all computers, where application run.
-- Computers set, where application run, does not depend on specified period by design, as otherwise there is performance problems
MachineCPUUndefinedFlag AS
(
SELECT
sf.SOURCEID,
MIN(COALESCE(m.CPUCount, -1)) AS CPUUndefinedFlag
FROM
#PROCESSFORSOURCE AS sf
JOIN apm.Machine AS m (NOLOCK) ON sf.MACHINEID = m.MachineId
GROUP BY
sf.SOURCEID
)
SELECT
-- Convert to ISO8601 format to work properly with VB Script. This cannot be done earlier as join is done on this fields
CONVERT(DATETIME, SourcesDates.ClientDate, 126) AS ClientDate,
-- These fake fields are need to provide compatibility with SP ApplicationStatusDrillthrough
1 AS Date,
0 AS Hours,
1 AS OutputDate,
1 AS Period,
SourcesDates.Sourceid,
SourcesDates.Source AS Source,
COALESCE(pc.CurReqCount, 0) AS CurMonitoredRequestSum,
COALESCE(pc.LastReqCount, 0) AS LastMonitoredRequestSum,
COALESCE(pc.AvgReqCount, 0) AS AvgMonitoredRequestSum,
COALESCE(pc.CurAvgReqTime, 0) AS CurAvgReqTime,
COALESCE(pc.LastAvgReqTime, 0) AS LastAvgReqTime,
COALESCE(pc.AvgReqTime, 0) AS AvgReqTime,
COALESCE(pc.CurCPUSum, 0) AS CurCPUValue,
COALESCE(pc.lastCPUSum, 0) AS LastCPUValue,
COALESCE(pc.AvgCPUSum, 0) AS AvgValue,
COALESCE(pc.CurMemSum, 0) AS CurMemValue,
COALESCE(pc.LastMemSum, 0) AS LastMemValue,
COALESCE(pc.AvgMemSum, 0) AS AvgMemValue,
COALESCE(pc.CurIOSum, 0) AS CurIOValue,
COALESCE(pc.LastIOSum, 0) AS LastIOValue,
COALESCE(pc.AvgIOSum, 0) AS AvgIOValue,
COALESCE(e.CurrentEventsCount, 0) AS NewEventsCount,
COALESCE(e.LasEventsCount, 0) AS OldEventsCount,
COALESCE(e.AvgEventsCount, 0) AS AvgEventsCount,
-- cpuFlag.CPUUndefinedFlag is null for current source if there is no one PCounter row
-- in PerfHourly table for specified period. If so, there is no need to show message about it
COALESCE(cpuFlag.CPUUndefinedFlag, 1) AS CPUUndefinedFlag,
CASE LEFT(AppPool.AppPoolInfo,1)
WHEN N'''' THEN N''
WHEN N'' THEN ''
ELSE REPLACE(LEFT(AppPool.AppPoolInfo, LEN(AppPool.AppPoolInfo)-1), N'''', N'')
END AS pool,
E.SeViewerAddress
FROM
SourcesDates
LEFT OUTER JOIN MachineCPUUndefinedFlag AS cpuFlag ON SourcesDates.Sourceid = cpuFlag.Sourceid
LEFT OUTER JOIN ActivePreparePCounters AS pc ON (pc.ClientDate = SourcesDates.ClientDate AND pc.SourceId = SourcesDates.Sourceid)
LEFT OUTER JOIN Events AS e ON (e.ClientDate = SourcesDates.ClientDate AND e.Sourceid = SourcesDates.Sourceid)
JOIN SourceAppPools AS AppPool ON (AppPool.Sourceid = SourcesDates.Sourceid)
ORDER BY
Source,
ClientDate
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.ApplicationActivityBreakdown'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.ApplicationActivityBreakdown AS RETURN 1')
END
GO

/****************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: ApplicationActivityBreakdown */
/* USED IN: Application Status Report, Application Activity */
/* DESCRIPTION: Temporary SP which provides unique call for different group by */
/* parameters, which realy need different SP */
/* INPUT PARAMETERS: */
/* @SOURCEIDS - List of the source id, separated by comma. Exp: '1,2,3' */
/* @COMPUTERIDS - List of the computer id, separated by comma. Exp: '1,2,3' */
/* @ENDDATE - End date of the period */
/* @PERIOD - Period type(Day, Week or Month). */
/* - Use for the Start Date calculate of the period */
/* @AVERAGEINTERVAL- This value specifies interval, for which average values will */
/* be calculated. Possible values: 1(1 month), 2(2 month), */
/* 3(3 month), 6(6 month), 17 (7 day) */
/* @GROUPBY - Specifies result gouping type. Possible values: */
/* Hour - Group by hours. Rersult set will contain 24 rows */
/* corresponding to 24 hours. Date field - 0-23, Hour field - 0 */
/* WeekDay - Group by week days. For this grouping type extra grouping */
/* is applied - by hours. So result data set contains 7*24 rows. */
/* Date field values - 1-7, Hour fields - 0-23 */
/* Month - Group by Month. For this grouping type extra grouping */
/* is applied - by months. So result data set contains 12*24 rows. */
/* and Hour field - 0-23 */
/* @TRESHOLD - Event duration treshold */
/* @PROBLEM - Event problem type (all, critical) */
/* @TIMEZONE - correlate parameter (timezone by min) */
/* - for the End Date calculate */
/****************************************************************************************/
alter PROCEDURE APM.ApplicationActivityBreakdown
@SOURCEIDS NVARCHAR(MAX),
@COMPUTERIDS NVARCHAR(MAX),
@ENDDATE DATETIME,
@TIMEZONE INT,
@PERIOD INT,
@AVERAGEINTERVAL INT,
@GROUPBY NVARCHAR(10),
@THRESHOLD INT,
@PROBLEM NVARCHAR(10),
@PMSTATUS NVARCHAR(50)
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON;

IF @GROUPBY = 'MonthDay'
exec APM.ApplicationActivityBreakdownByMonthDate
@SOURCEIDS,
@COMPUTERIDS,
@ENDDATE,
@TIMEZONE,
@PERIOD,
@AVERAGEINTERVAL,
@GROUPBY,
@THRESHOLD,
@PROBLEM,
@PMSTATUS
ELSE
exec APM.ApplicationStatusDrillthrough
@SOURCEIDS,
@COMPUTERIDS,
@ENDDATE,
@TIMEZONE,
@PERIOD,
@AVERAGEINTERVAL,
@GROUPBY,
@THRESHOLD,
@PROBLEM,
@PMSTATUS
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.SummaryUserAnalysisCSM'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.SummaryUserAnalysisCSM AS RETURN 1')
END
GO

/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME:SummaryUserAnalysisCSM */
/* USED IN: Summary User Analysis Report - summary table */
/* INPUT PARAMETERS: */
/* @STARTDATE - Start date of the priod */
/* @ENDDATE - End date of the period */
/* @SOURCEIDS - List of source Id, separated by comma. Exp: '1,2,3' */
/* @MACHINEIDS - List of machine Id, separated by comma. Exp: '4,5,6' */
/* @INCLUDESUBNET - Subnet masks list, which should be included */
/* @EXCLUDESUBNET - Subnet mask list, which should be excluded */
/* @ORDERBY - Specifies column ordering should be applied */
/* 1 - EventCount */
/* 2 - ProblemCount */
/* 3 - PerformanceEventCount */
/* 4 - ExceptionEventCount */
/* 5 - MaxTotalTime */
/* 6 - TotalTime */
/* 7 - MaxTotalSize */
/* 8 - TotalSize */
/************************************************************************************/
/* This stored procedure returns top 10 users ordered by user defined input */
/* parameter @ORDERBY. Every user have exactly five records of data with top five */
/* page,java script and ajax, exception events ordered by events count of each */
/* specific event. */
/* Each record is also contains overall statistics for the Summary table and */
/* charts. */
/************************************************************************************/
alter PROCEDURE [APM].[SummaryUserAnalysisCSM]
@STARTDATE DATETIME,
@ENDDATE DATETIME,
@SOURCEIDS NVARCHAR(MAX),
@MACHINEIDS NVARCHAR(MAX),
@INCLUDESUBNET NVARCHAR(MAX),
@EXCLUDESUBNET NVARCHAR(MAX),
@THRESHOLD DECIMAL(35,0),
@ORDERBY INT,
@PMSTATUS NVARCHAR(50)
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON

SELECT
@INCLUDESUBNET = REPLACE(@INCLUDESUBNET, N'*', N'%'),
@EXCLUDESUBNET = REPLACE(@EXCLUDESUBNET, N'*', N'%')

-- Filter table, which contains machine ids and source ids
-- typeid defines filter type - 1 for source and 2 for machine
-- valueId filter value - source id and machine id
CREATE TABLE #SOURCEMACHINEFILTERTABLE(
TYPEID INT,
VALUEID INT
)

-- Fill table #SOURCEMACHINEFILTERTABLE
INSERT INTO #SOURCEMACHINEFILTERTABLE
SELECT
p.typeId AS TYPEID,
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@SOURCEIDS, @MACHINEIDS) AS p

-- Filter table, which contains PM Statuses of Events
CREATE TABLE #PMSTATUSFILTERTABLE(
VALUEID INT
)

-- Fill table #PMSTATUSFILTERTABLE
INSERT
INTO #PMSTATUSFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@PMSTATUS, N'') AS p

-- Filter table for SubnetC values
CREATE TABLE #SUBNETCFILTERTABLE
(
IPID INT,
SUBNETC NVARCHAR(50) collate database_default
)

-- Insert into filter id of the SubnetC to increase performence for event table
INSERT INTO #SUBNETCFILTERTABLE
SELECT DISTINCT
ipid,
ip.SubNetC
FROM
apm.IP AS ip (NOLOCK)
JOIN APM.GetMultiParameters(CASE WHEN LEN(@INCLUDESUBNET) &gt; 0 THEN @INCLUDESUBNET ELSE N'%' END, N'') AS p1 ON (ip.SubnetC LIKE p1.Value)
LEFT OUTER JOIN APM.GetMultiParameters(CASE WHEN LEN(@EXCLUDESUBNET) &gt; 0 THEN @EXCLUDESUBNET ELSE N'Fake' END, N'') AS p2 ON (ip.SubnetC LIKE p2.Value)
WHERE
--Exclude subnets which have correspondance in @EXCLUDESUBNET parameter
p2.typeId IS NULL


/*************************************************** Main Query ***************************************************/

-- Calculating information about Page events
;WITH PageEvents AS
(
SELECT
NULL AS classType,
ROW_NUMBER() OVER(PARTITION BY UserId ORDER BY COUNT(CSEventId) DESC, PageUri ASC) AS RowId,
PageUri,
UserId,
COUNT(CSEventId) AS EventCount,
COUNT(DISTINCT CSEventGroup) AS ProblemCount,
AVG(NetworkTime) AS NetworkTime,
AVG(ServerTime) AS ServerTime,
AVG(DOMTime) AS DOMTime,
AVG(PeripheralTime) AS PeripheralTime,
AVG(OnLoadTime) AS OnLoadTime,
AVG(TotalTime) AS TotalTime,
AVG(TotalSize) AS TotalSize,
-- This value is needed for ordering by maximum total time in the summary table
MAX(MAX(TotalTime)) OVER(PARTITION BY UserId) AS MaxTotalTime,
-- These values are needed to calculate average event duration and average size for user
SUM(SUM(TotalTime)) OVER(PARTITION BY UserId) AS UserSumTime,
SUM(SUM(TotalSize)) OVER(PARTITION BY UserId) AS UserSumSize,
-- This value is page event count for current user
SUM(COUNT(*)) OVER(PARTITION BY UserId) AS UserPageEventCount,
-- These values are needed to calculate average times for current page (information for "all" chart)
SUM(COUNT(*)) OVER(PARTITION BY PageUri) AS SamePageEventCount,
SUM(SUM(NetworkTime)) OVER(PARTITION BY PageUri) AS AvgPageNetworkTime,
SUM(SUM(ServerTime)) OVER(PARTITION BY PageUri) AS AvgPageServerTime,
SUM(SUM(DOMTime)) OVER(PARTITION BY PageUri) AS AvgPageDOMTime,
SUM(SUM(PeripheralTime)) OVER(PARTITION BY PageUri) AS AvgPagePeripheralTime,
SUM(SUM(OnLoadTime)) OVER(PARTITION BY PageUri) AS AvgPageOnLoadTime,
COUNT(UserId) OVER(PARTITION BY PageUri) AS AffectedUserCount
FROM
(
SELECT
e.CSEventId,
MAX(e.PageUri) AS PageUri,
MAX(e.UserId) AS UserId,
MAX(e.CSEventGroupId) AS CSEventGroup,
MAX(COALESCE(p.NetworkTime,0))/1000 AS NetworkTime,
MAX(COALESCE(p.ServerTime,0))/1000 AS ServerTime,
MAX(COALESCE(p.DOMTime,0))/1000 AS DOMTime,
MAX(COALESCE(p.PeripheralTime,0))/1000 AS PeripheralTime,
MAX(COALESCE(p.OnLoadTime,0))/1000 AS OnLoadTime,
MAX(p.TotalTime)/1000 AS TotalTime,
MAX(COALESCE(CAST(p.TotalSize AS DECIMAL(35,2)),0))/1024 + SUM(COALESCE(CAST(a.ResponseSize AS DECIMAL(35,2)),0) + COALESCE(CAST(a.REQUESTSIZE AS DECIMAL(35,2)),0))/1024 AS TotalSize
FROM
apm.CSEvent AS e (NOLOCK)
JOIN #SOURCEMACHINEFILTERTABLE AS f1 ON (f1.VALUEID = e.SourceId AND f1.TYPEID = 1)
JOIN #SOURCEMACHINEFILTERTABLE AS f2 ON (f2.VALUEID = e.MachineId AND f2.TYPEID = 2)
JOIN #SUBNETCFILTERTABLE AS f3 ON e.ipid = f3.IPID
JOIN #PMSTATUSFILTERTABLE AS f4 ON (f4.VALUEID = e.PMStatus)
JOIN apm.CSPageEvent AS p (NOLOCK) ON e.CSEventId = p.CSEventId
LEFT OUTER JOIN apm.CSAjax AS a (NOLOCK) ON e.CSEventId = a.CSEventId
WHERE
e.UTCDate &gt;= @STARTDATE
AND e.UTCDate &lt; @ENDDATE
AND e.UserId IS NOT NULL
AND e.PageUri IS NOT NULL
AND p.TotalTime/1000.0 &gt;= @THRESHOLD
GROUP BY
E.CSEventId /* Grouping by Id of the specific event to be able to
summarize data of page event with Ajax ones which
were generated by it. */
) AS pe
GROUP BY
PageUri,
UserId
),
-- Calculating information about Java script and Ajax events
JSandAjaxEvents AS
(
SELECT
classType,
ROW_NUMBER() OVER(PARTITION BY UserId ORDER BY COUNT(EventId) DESC, PageUri, [Action] ASC) AS RowId,
UserId,
PageUri,
[Action],
COUNT(*) AS EventCount,
COUNT(DISTINCT EventGroupId) AS ProblemCount,
AVG(NetworkTime) AS NetworkTime,
AVG(ServerTime) AS ServerTime,
AVG(TotalTime - NetworkTime - ServerTime) AS ClientTime,
AVG(TotalTime) AS TotalTime,
-- This value is needed for ordering by maximum total time in the summary table
MAX(MAX(TotalTime)) OVER(PARTITION BY UserId) AS MaxTotalTime,
AVG(TotalSize) AS TotalSize,
SUM(SUM(TotalSize)) OVER(PARTITION BY UserId) AS UserSumSize,
SUM(SUM(NetworkTime)) OVER(PARTITION BY PageUri,[Action]) AS AllNetworkTime,
SUM(SUM(ServerTime)) OVER(PARTITION BY PageUri,[Action]) AS AllServerTime,
SUM(SUM(TotalTime - NetworkTime - ServerTime)) OVER(PARTITION BY PageUri,[Action]) AS AllClientTime,
SUM(SUM(TotalTime)) OVER(PARTITION BY PageUri,[Action]) AS AllTotalTime,
SUM(SUM(TotalTime)) OVER(PARTITION BY UserId) AS UserSumTime,
COUNT(UserId) OVER(PARTITION BY PageUri,[Action]) AS AffectedUserCount,
SUM(COUNT(*)) OVER(PARTITION BY UserId) AS TotalUserEventCount,
SUM(COUNT(*)) OVER(PARTITION BY PageUri,[Action]) AS TotalPageEventCount
FROM
(
SELECT
MAX(CASE WHEN COALESCE(a.Synchronous,1) = 0 THEN 1 ELSE 2 END) AS classType,
e.CSEventId AS EventId,
MAX(e.UserId) AS UserId,
MAX(e.CSEventGroupId) AS EventGroupId,
MAX(e.PageUri) AS PageUri,
MAX(CASE WHEN COALESCE(a.Synchronous,1) = 0 THEN a.Uri ELSE j.Action END) AS [Action],
SUM((COALESCE(a.NetworkTime,0) + COALESCE(a.ResponseTime,0))/1000) AS NetworkTime,
SUM(COALESCE(a.ServerTime,0))/1000 AS ServerTime,
MAX(COALESCE(j.TotalTime, a.TotalTime))/1000 AS TotalTime,
CAST(SUM(COALESCE(a.REQUESTSIZE,0) + COALESCE(a.ResponseSize,0)) AS DECIMAL(35,2))/1024 AS TotalSize
FROM
apm.CSEvent (NOLOCK) as e
JOIN #SOURCEMACHINEFILTERTABLE AS f1 ON (f1.VALUEID = e.SourceId AND f1.TYPEID = 1)
JOIN #SOURCEMACHINEFILTERTABLE AS f2 ON (f2.VALUEID = e.MachineId AND f2.TYPEID = 2)
JOIN #SUBNETCFILTERTABLE AS f3 ON e.ipid = f3.IPID
JOIN #PMSTATUSFILTERTABLE AS f4 ON (f4.VALUEID = e.PMStatus)
LEFT OUTER JOIN apm.CSJScriptEvent AS j ON e.CSEventId = j.CSEventId
LEFT OUTER JOIN apm.CSAjax AS a ON e.CSEventId = a.CSEventId
WHERE
e.UTCDate &gt;= @STARTDATE
AND e.UTCDate &lt; @ENDDATE
AND e.UserId IS NOT NULL
AND e.PageUri IS NOT NULL
AND e.EventClass &lt;&gt; N'CSMPMonitorLog'
AND e.CLassType = N'performance'
AND COALESCE(j.TotalTime, a.TotalTime)/1000.0 &gt;= @THRESHOLD
GROUP BY
e.CSEventId
) AS jsax
GROUP BY
jsax.UserId,
jsax.PageUri,
jsax.Action,
jsax.classType
),
-- Prepairing template in which every user will have exactly five rows for top page, exceptionevents
PreResultTemplate AS
(
SELECT
UserId
FROM
apm.CSEvent (NOLOCK) AS e
JOIN #SOURCEMACHINEFILTERTABLE AS f1 ON (f1.VALUEID = e.SourceId AND f1.TYPEID = 1)
JOIN #SOURCEMACHINEFILTERTABLE AS f2 ON (f2.VALUEID = e.MachineId AND f2.TYPEID = 2)
JOIN #SUBNETCFILTERTABLE AS f3 ON e.ipid = f3.IPID
JOIN #PMSTATUSFILTERTABLE AS f4 ON (f4.VALUEID = e.PMStatus)
WHERE
UTCDate &gt;= @STARTDATE
AND UTCDate &lt; @ENDDATE
AND PageUri IS NOT NULL
AND UserId IS NOT NULL
GROUP BY
UserId
),
ResultTemplate AS -- Template which has exactly 5 rows for each user
(
SELECT
pr.UserId,
n.n AS RowId
FROM
PreResultTemplate as pr
CROSS JOIN APM.fn_numS(5) AS n
),
-- Calculating information about Exception events
ExceptionEvents AS
(
SELECT
4 AS classType,
ROW_NUMBER() OVER(PARTITION BY UserId ORDER BY COUNT(CSEventId) DESC, [Description] ASC) AS RowId,
UserId,
Description,
COUNT(CSEventId) AS EventCount,
COUNT(DISTINCT CSEventGroupId) AS ProblemCount,
COUNT(CASE WHEN CHARINDEX(N'MSIE', E.Browser) &gt; 0 THEN E.CSEventId END) AS IEEventCount,
COUNT(CASE WHEN CHARINDEX(N'Firefox', E.Browser) &gt; 0 THEN E.CSEventId END) AS FirefoxEventCount,
AVG(COUNT(CSEventId)*1.0) OVER(PARTITION BY [Description]) AS AllEventCount,
AVG(COUNT(CASE WHEN CHARINDEX(N'MSIE', E.Browser) &gt; 0 THEN E.CSEventId END)*1.0) OVER(PARTITION BY [Description]) AS AllIEEventCount,
AVG(COUNT(CASE WHEN CHARINDEX(N'Firefox', E.Browser) &gt; 0 THEN E.CSEventId END)*1.0) OVER(PARTITION BY [Description]) AS AllFirefoxEventCount,
COUNT(UserId) OVER(PARTITION BY [Description]) AS AffectedUserCount,
SUM(COUNT(CSEventId)) OVER(PARTITION BY UserId) AS UserEventCount
FROM
apm.CSEvent (NOLOCK) AS e
JOIN #SOURCEMACHINEFILTERTABLE AS f1 ON (f1.VALUEID = e.SourceId AND f1.TYPEID = 1)
JOIN #SOURCEMACHINEFILTERTABLE AS f2 ON (f2.VALUEID = e.MachineId AND f2.TYPEID = 2)
JOIN #SUBNETCFILTERTABLE AS f3 ON e.ipid = f3.IPID
JOIN #PMSTATUSFILTERTABLE AS f4 ON (f4.VALUEID = e.PMStatus)
WHERE
e.UTCDate &gt;= @STARTDATE
AND e.UTCDate &lt; @ENDDATE
AND e.UserId IS NOT NULL
AND e.PageUri IS NOT NULL
AND e.ClassType = N'exception'
GROUP BY
UserId,
[Description]
),
-- Summarizing data from PageEvents, ExceptionEvents and JSandAjaxEvents CTE's
ResultTable AS
(
SELECT
/* Create additional field to have an ability to sort out the unusual events when
creating URLs*/
js.classType,
/* Create additional field for sorting according to the @ORDERBY input parameter.
Selecting maximum value of selected field for each user. */
CASE @ORDERBY
WHEN 1 THEN MAX(COALESCE(ex.UserEventCount,0) + COALESCE(pg.UserPageEventCount,0) + COALESCE(js.TotalUserEventCount,0)) OVER(PARTITION BY rt.UserId)
WHEN 2 THEN SUM(COALESCE(ex.ProblemCount,0) + COALESCE(pg.ProblemCount,0) + COALESCE(js.ProblemCount,0)) OVER(PARTITION BY rt.UserId)
WHEN 3 THEN MAX(COALESCE(pg.EventCount,0)) OVER(PARTITION BY rt.UserId)
WHEN 4 THEN MAX(COALESCE(ex.EventCount,0)) OVER(PARTITION BY rt.UserId)
-- Choosing the maximum value from the page and javascript event
WHEN 5 THEN
MAX(CASE WHEN COALESCE(pg.MaxTotalTime,0) &gt;= COALESCE(js.MaxTotalTime,0)
THEN COALESCE(pg.MaxTotalTime,0)
ELSE COALESCE(js.MaxTotalTime,0)
END) OVER(PARTITION BY rt.UserId)
-- Caculating average user page, ajax and javascript event time
WHEN 6 THEN
(CASE WHEN (MAX(COALESCE(pg.UserPageEventCount,0) + COALESCE(js.TotalUserEventCount,0))OVER(PARTITION BY rt.UserId)) &gt; 0
THEN (MAX(COALESCE(pg.UserSumTime,0) + COALESCE(js.UserSumTime,0)) OVER(PARTITION BY rt.UserId))/(MAX(COALESCE(pg.UserPageEventCount,0) + COALESCE(js.TotalUserEventCount,0)) OVER(PARTITION BY rt.UserId))
ELSE 0
END)
-- Calculating average user page, ajax and javascript event size
WHEN 7 THEN
(CASE WHEN (MAX(COALESCE(pg.UserPageEventCount,0) + COALESCE(js.TotalUserEventCount,0)) OVER(PARTITION BY rt.UserId))&gt; 0
THEN (MAX(COALESCE(pg.UserSumSize,0) + COALESCE(js.UserSumSize,0)) OVER(PARTITION BY rt.UserId))/(max(COALESCE(pg.UserPageEventCount,0)+COALESCE(js.TotalUserEventCount,0))OVER(PARTITION BY rt.UserId))
ELSE 0
END)
END AS OrderData,
rt.RowId,
rt.UserId,
(CASE WHEN (MAX(COALESCE(pg.UserPageEventCount,0) + COALESCE(js.TotalUserEventCount,0)) OVER(PARTITION BY rt.UserId))&gt; 0
THEN (MAX(COALESCE(pg.UserSumSize,0) + COALESCE(js.UserSumSize,0)) OVER(PARTITION BY rt.UserId))/(max(COALESCE(pg.UserPageEventCount,0)+COALESCE(js.TotalUserEventCount,0))OVER(PARTITION BY rt.UserId))
ELSE 0
END) AS UserAvgSize,
(CASE WHEN (MAX(COALESCE(pg.UserPageEventCount,0) + COALESCE(js.TotalUserEventCount,0))OVER(PARTITION BY rt.UserId)) &gt; 0
THEN (MAX(COALESCE(pg.UserSumTime,0) + COALESCE(js.UserSumTime,0)) OVER(PARTITION BY rt.UserId))/(MAX(COALESCE(pg.UserPageEventCount,0) + COALESCE(js.TotalUserEventCount,0)) OVER(PARTITION BY rt.UserId))
ELSE 0
END) AS UserAvgTime,
-- Summarize problems count between all issues as this information is shown in summary table for user
SUM(COALESCE(ex.ProblemCount,0) + COALESCE(pg.ProblemCount,0) + COALESCE(js.ProblemCount,0)) OVER(PARTITION BY rt.UserId) AS ProblemCount,
MAX((COALESCE(ex.UserEventCount,0) + COALESCE(pg.UserPageEventCount,0) + COALESCE(js.TotalUserEventCount,0))) OVER(PARTITION BY rt.UserId) AS EventCount,
-- Exception events details --
(ex.Description) AS Ex_Description,
(ex.EventCount) AS Ex_EventCount,
(ex.IEEventCount) AS Ex_IEEventCount,
(ex.FireFoxEventCount) AS Ex_FireFoxEventCount,
(ex.AllEventCount) AS Ex_AllEventCount,
(ex.AllIEEventCount) AS Ex_AllIEEventCount,
(ex.AllFirefoxEventCount) AS Ex_AllFirefoxEventCount,
(ex.AffectedUserCount) AS Ex_AffectedUserCount,
MAX(COALESCE(ex.UserEventCount,0)) OVER(PARTITION BY rt.UserId) AS Ex_UserEventCount,
-- Page events details --
(pg.PageUri) AS Pg_PageUri,
(pg.MaxTotalTime) AS Pg_MaxTotalTime,
(pg.EventCount) AS Pg_EventCount,
(pg.NetworkTime) AS Pg_NetworkTime,
(pg.ServerTime) AS Pg_ServerTime,
(pg.DOMTime) AS Pg_DOMTime,
(pg.PeripheralTime) AS Pg_PeripheralTime,
(pg.OnLoadTime) AS Pg_OnLoadTime,
(pg.TotalTime) AS Pg_TotalTime,
(pg.TotalSize) AS Pg_TotalSize,
(pg.AvgPageNetworkTime / pg.SamePageEventCount) AS Pg_AvgPageNetworkTime,
(pg.AvgPageServerTime / pg.SamePageEventCount) AS Pg_AvgPageServerTime,
(pg.AvgPageDOMTime / pg.SamePageEventCount) AS Pg_AvgPageDOMTime,
(pg.AvgPagePeripheralTime / pg.SamePageEventCount) AS Pg_AvgPagePeripheralTime,
(pg.AvgPageOnLoadTime / pg.SamePageEventCount) AS Pg_AvgPageOnLoadTime,
(pg.AffectedUserCount) AS Pg_AffectedUserCount,
(pg.UserSumTime / pg.UserPageEventCount) AS Pg_AvgUserTime,
(pg.UserSumSize / pg.UserPageEventCount) AS Pg_AvgUserSize,
MAX(pg.UserPageEventCount) OVER(PARTITION BY rt.UserId) AS Pg_UserPageEventCount,
-- Javascript and Ajax events details --
(js.PageUri) AS Js_PageUri,
(js.Action) AS Js_Action,
(js.MaxTotalTime) AS Js_MaxTotalTime,
(js.EventCount) AS Js_EventCount,
(js.NetworkTime) AS Js_NetworkTime,
(js.ServerTime) AS Js_ServerTime,
(js.ClientTime) AS Js_ClientTime,
(js.TotalTime) AS Js_TotalTime,
(js.TotalSize) AS Js_TotalSize,
(js.AllNetworkTime / js.TotalPageEventCount) AS Js_AllNetworkTime,
(js.AllServerTime / js.TotalPageEventCount) AS Js_AllServerTime,
(js.AllClientTime / js.TotalPageEventCount) AS Js_AllClientTime,
(js.AllTotalTime / js.TotalPageEventCount) AS Js_AllTotalTime,
js.AffectedUserCount AS Js_AffectedUserCount,
MAX(COALESCE(js.TotalUserEventCount,0)) OVER(PARTITION BY rt.UserId) AS Js_TotalUserEventCount
FROM
ResultTemplate AS rt
LEFT OUTER JOIN ExceptionEvents AS ex ON ex.UserId = rt.UserId AND ex.RowId = rt.RowId
LEFT OUTER JOIN PageEvents AS pg ON pg.UserId = rt.UserId AND pg.RowId = rt.RowId
LEFT OUTER JOIN JSandAjaxEvents AS js ON js.UserId = rt.UserId AND js.RowId = rt.RowId
)
SELECT
TOP 50
res.classType,
res.OrderData, -- As we have exactly 5 rows for each user, we select the first ten of them.
res.RowId,
u.Name,
res.ProblemCount,
res.EventCount,
res.UserAvgSize,
res.UserAvgTime,
res.Ex_Description,
res.Ex_EventCount,
res.Ex_IEEventCount,
res.Ex_FireFoxEventCount,
res.Ex_AllEventCount,
res.Ex_AllIEEventCount,
res.Ex_AllFirefoxEventCount,
res.Ex_AffectedUserCount,
res.Ex_UserEventCount,
res.Pg_PageUri,
res.Pg_MaxTotalTime,
res.Pg_EventCount,
res.Pg_NetworkTime,
res.Pg_ServerTime,
res.Pg_DOMTime,
res.Pg_PeripheralTime,
res.Pg_OnLoadTime,
res.Pg_TotalTime,
res.Pg_TotalSize,
res.Pg_AvgPageNetworkTime,
res.Pg_AvgPageServerTime,
res.Pg_AvgPageDOMTime,
res.Pg_AvgPagePeripheralTime,
res.Pg_AvgPageOnLoadTime,
res.Pg_AffectedUserCount,
res.Pg_AvgUserTime,
res.Pg_AvgUserSize,
res.Pg_UserPageEventCount,
res.Js_PageUri,
res.Js_Action,
res.Js_MaxTotalTime,
res.Js_EventCount,
res.Js_NetworkTime,
res.Js_ServerTime,
res.Js_ClientTime,
res.Js_TotalTime,
res.Js_TotalSize,
res.Js_AllNetworkTime,
res.Js_AllServerTime,
res.Js_AllClientTime,
res.Js_AllTotalTime,
res.Js_AffectedUserCount,
res.Js_TotalUserEventCount
FROM
ResultTable AS res
JOIN apm.Users AS u ON u.UserId = res.UserId
WHERE
-- This condition is set as users where not filtered by threshold, and ther could be situations when there is no events at all
-- for some user. Such users should not be selected. It wouldn't have affect on ordering as for such users all other values is 0
res.EventCount &gt; 0
ORDER BY
res.OrderData DESC,u.Name,res.Rowid
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.PCType_ConfigSync'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.PCType_ConfigSync AS RETURN 1')
END
GO


/****************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: PCType_ConfigSync */
/* USED IN: transfer routine : task=ConfigSynchronization;action=SyncPerfCountersAction */
/* DESCRIPTION: updates INSTANCEFUNCTION, DATEFUNCTION for counters, that are listed */
/* in configuration file */
/* INPUT PARAMETERS: */
/* @DESCRIPTORS - List of counters in XML format (aggregation/perfcounterSet */
/* @TRACELEVEL - service variable (error tracing level) */
/****************************************************************************************/
alter PROCEDURE APM.PCType_ConfigSync
@DESCRIPTORS NTEXT
,@TRACELEVEL INT
AS
BEGIN
SET NOCOUNT ON

DECLARE
@ERRORIND BIT
,@ERRORMESSAGE NVARCHAR(MAX)
,@ERRORNUMBER INT
,@ERRORSEVERITY INT
,@ERRORSTATE INT
,@ERRORLINE INT
,@ERRORPROCEDURE NVARCHAR(256)
,@ERRORMESSAGETEXT NVARCHAR(MAX)

BEGIN TRY

DECLARE @EXECRESULT INT
DECLARE @ROWCOUNT INT
DECLARE @HANDLER INT

-- Prepare xml document
EXEC SP_XML_PREPAREDOCUMENT @HANDLER OUTPUT, @DESCRIPTORS
IF @EXECRESULT &lt;&gt; 0
BEGIN
SELECT @ERRORMESSAGE = message FROM APM.messages WHERE id = 50002
RAISERROR(@ERRORMESSAGE, 16, 1, 'PCType_ConfigSync', @EXECRESULT)
END

-- Create temporary table for counters
CREATE TABLE #DESCRIPTORSET (
DESCRIPTOR NVARCHAR(255) collate database_default NOT NULL,
INSTANCEFUNCTION NVARCHAR(50) collate database_default NOT NULL,
DATEFUNCTION NVARCHAR(50) collate database_default NOT NULL
)

-- Fill table with date from xml
INSERT INTO #DESCRIPTORSET
SELECT NAME, COALESCE(INSTANCEFUNC,'AVG'), COALESCE(DATEFUNC,'AVG')
FROM OPENXML (@HANDLER, '/perfcounterSet/perfcounter', 1)
WITH (NAME NVARCHAR(255), INSTANCEFUNC NVARCHAR(50) , DATEFUNC NVARCHAR(50))
SET @ROWCOUNT = @@ROWCOUNT

EXEC SP_XML_REMOVEDOCUMENT @HANDLER

-- Update PCTYPE table with new aggregate function values
UPDATE T
SET T.INSTANCEFUNCTION = sync.INSTANCEFUNCTION,
T.DATEFUNCTION = sync.DATEFUNCTION
FROM apm.PCTYPE T
JOIN #DESCRIPTORSET sync ON sync.DESCRIPTOR = T.TYPE

END TRY
BEGIN CATCH
IF (@@TRANCOUNT &gt; 0)
ROLLBACK TRAN

SELECT
@ERRORNUMBER = ERROR_NUMBER()
,@ERRORSEVERITY = ERROR_SEVERITY()
,@ERRORSTATE = ERROR_STATE()
,@ERRORLINE = ERROR_LINE()
,@ERRORPROCEDURE = ISNULL(ERROR_PROCEDURE(), '-')
,@ERRORMESSAGETEXT = ERROR_MESSAGE()
SET @ERRORIND = 1
END CATCH

-- report error if any
IF (@ERRORIND = 1)
BEGIN
DECLARE @ADJUSTEDERRORSEVERITY int

SET @ADJUSTEDERRORSEVERITY = CASE
WHEN @ERRORSEVERITY = 2601 OR @ERRORSEVERITY = 2627 THEN 0
WHEN @ERRORSEVERITY &gt; 18 THEN 18
ELSE @ERRORSEVERITY
END

SELECT @ERRORMESSAGE = message FROM APM.Messages WHERE id = 50004
RAISERROR (@ERRORMESSAGE
,@ADJUSTEDERRORSEVERITY
,1
,@ERRORNUMBER
,@ERRORSEVERITY
,@ERRORSTATE
,@ERRORPROCEDURE
,@ERRORLINE
,@ERRORMESSAGETEXT
)
END
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.DeleteEventsOrEventGroups'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.DeleteEventsOrEventGroups AS RETURN 1')
END
GO


/****************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: DeleteEventsOrEventGroups */
/* DESCRIPTION: */
/* Delete events using #EVENTGROOM(eventid) table or delete eventgroup that hot have */
/* events and older @LASTKEEPDATE. Events will be delete if #EVENTGROOM table is not */
/* empty otherwise event groups will be deleted */
/* INPUT PARAMETERS: */
/* @ROWSPERITERATION - number of records that have been deleted by one delete */
/* instruction */
/* @CLIENT - 1:client events 0:server events */
/* @LASTKEEPDATE - last keep date. It use for delete event groups */
/* OUTPUT PARAMETERS: */
/* @ROWSAFFECTED - Number of deleted events or event groups */
/****************************************************************************************/
alter PROCEDURE APM.DeleteEventsOrEventGroups
@ROWSPERITERATION int
,@CLIENT bit
,@LASTKEEPDATE datetime
,@ROWSAFFECTED int OUTPUT
AS
SET @ROWSAFFECTED = 0
IF @CLIENT = 0
BEGIN
--delete server events
IF EXISTS(SELECT * FROM #EVENTGROOM)
BEGIN
--- Grooming performance node ---------
DELETE pn
FROM APM.PerformanceNode AS pn
JOIN #EVENTGROOM AS eventFilter ON pn.eventid = eventFilter.EVENTID

--- Grooming resource group node ---------
DELETE rgn
FROM APM.ResourceGroupNode AS rgn
JOIN #EVENTGROOM AS eventFilter ON rgn.eventid = eventFilter.EVENTID

--- Grooming exception node ---------
DELETE en
FROM APM.ExceptionNode AS en
JOIN #EVENTGROOM AS eventFilter ON en.eventid = eventFilter.EVENTID

-- Grooming server detail events ---
DELETE ed
FROM APM.eventdetail AS ed
JOIN #EVENTGROOM AS eventFilter ON ed.eventid = eventFilter.EVENTID

DELETE e
FROM APM.Event AS e
JOIN #EVENTGROOM AS eventFilter ON e.eventid = eventFilter.EVENTID

SELECT @ROWSAFFECTED = @@ROWCOUNT
END
ELSE
BEGIN
-- delete server event groups
WHILE EXISTS (SELECT * FROM APM.EventGroup G
WHERE G.LASTEVENTDATE &lt; @LASTKEEPDATE
AND NOT EXISTS(SELECT * FROM EVENT e WHERE e.eventgroupId = G.EventGroupId)
)
BEGIN
DELETE TOP (@ROWSPERITERATION) g
FROM APM.EventGroup AS g
WHERE G.LASTEVENTDATE &lt; @LASTKEEPDATE
AND NOT EXISTS(SELECT * FROM EVENT e WHERE e.eventgroupId = G.EventGroupId)

SELECT @ROWSAFFECTED = @ROWSAFFECTED + @@ROWCOUNT
END
END
END
IF @CLIENT = 1
BEGIN
-- delete client events
IF EXISTS(SELECT * FROM #EVENTGROOM)
BEGIN
-- Grooming PageEvent-----
DELETE pe
FROM APM.cspageevent AS pe
JOIN #EVENTGROOM AS eventFilter ON pe.cseventid = eventFilter.EVENTID

-- Grooming Peripheral Details -----
DELETE pd
FROM APM.csperipheraldetail AS pd
JOIN APM.csperipheral AS pe ON pe.csperipheralId = pd.csperipheralId
JOIN #EVENTGROOM AS eventFilter ON pe.cseventid = eventFilter.EVENTID

-- Grooming Peripheral ------
DELETE pe
FROM APM.csperipheral AS pe
JOIN #EVENTGROOM AS eventFilter ON pe.cseventid = eventFilter.EVENTID

-- Grooming csHeaviestResource ---
DELETE hr
FROM APM.csHeaviestResource AS hr
JOIN #EVENTGROOM AS eventFilter ON hr.cseventid = eventFilter.EVENTID

-- Grooming ajax events ---
DELETE aj
FROM APM.csAjax AS aj
JOIN #EVENTGROOM AS eventFilter ON aj.cseventid = eventFilter.EVENTID

-- Grooming async ajax events ---
DELETE aj
FROM APM.csAsyncAjax AS aj
JOIN #EVENTGROOM AS eventFilter ON aj.cseventid = eventFilter.EVENTID

-- Grooming async jscript events ---
DELETE js
FROM APM.csJScriptEvent AS js
JOIN #EVENTGROOM AS eventFilter ON js.cseventid = eventFilter.EVENTID

-- Grooming client exception events ---
DELETE ex
FROM APM.csexevent AS ex
JOIN #EVENTGROOM AS eventFilter ON ex.cseventid = eventFilter.EVENTID

-- Grooming client detail events ---
DELETE ed
FROM APM.cseventdetail AS ed
JOIN #EVENTGROOM AS eventFilter ON ed.cseventid = eventFilter.EVENTID

-- Grooming client events ---
DELETE ev
FROM APM.csEvent ev
JOIN #EVENTGROOM AS eventFilter ON ev.cseventid = eventFilter.EVENTID

SELECT @ROWSAFFECTED = @@ROWCOUNT
END
ELSE
BEGIN
--delete client groups
WHILE EXISTS (SELECT * FROM APM.csEventGroup g
WHERE g.lasteventdate &lt; @LASTKEEPDATE
AND NOT EXISTS(SELECT * FROM csEvent e WHERE e.cseventgroupId = g.csEventGroupId)
)
BEGIN
DELETE TOP (@ROWSPERITERATION) g
FROM APM.csEventGroup AS g
WHERE g.lasteventdate &lt; @LASTKEEPDATE
AND NOT EXISTS(SELECT * FROM csEVENT e WHERE e.cseventgroupId = g.csEventGroupId)

SELECT @ROWSAFFECTED = @ROWSAFFECTED + @@ROWCOUNT
END
END
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.ExtractEventGroomingRows'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.ExtractEventGroomingRows AS RETURN 1')
END
GO
/****************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: ExtractEventGroomingRows */
/* DESCRIPTION: */
/* It fill #EVENTGROOM(eventid) table from server or client events by date and status */
/* INPUT PARAMETERS: */
/* @ROWSPERITERATION - number of records that have been selected from underline table */
/* @LASTKEEPDATE - last keep date. */
/* @DATABASEID - database primary key from seviewerdb table */
/* @CLIENT - 1:client events 0:server events */
/* @PMSTATUS - problem management */
/****************************************************************************************/
alter PROCEDURE [APM].[ExtractEventGroomingRows]
@ROWSPERITERATION int
,@LASTKEEPDATE datetime
,@DATABASEID int
,@CLIENT bit
,@PMSTATUS tinyint
AS
SET NOCOUNT ON

IF @CLIENT = 0
BEGIN
--server events
IF @PMSTATUS IS null
INSERT #EVENTGROOM
SELECT TOP(@ROWSPERITERATION) e.EventId
FROM APM.event (NOLOCK) AS e
WHERE
e.SEVIEWERDBID = @DATABASEID AND
e.UTCEVENTDATE &lt; @LASTKEEPDATE
ELSE
INSERT #EVENTGROOM
SELECT TOP(@ROWSPERITERATION) e.EventId
FROM APM.EVENT (NOLOCK) E
JOIN apm.PMSERVEREVENTTRACE (NOLOCK) ET ON E.EVENTID = ET.EVENTID
JOIN apm.PMTRACE PT (NOLOCK) ON PT.PMTRACEID = ET.PMTRACEID
WHERE
e.PMSTATUS = @PMSTATUS AND
e.UTCEVENTDATE &lt; @LASTKEEPDATE AND
e.SEVIEWERDBID = @DATABASEID
GROUP BY
E.EVENTID
HAVING
MAX(PT.UTCDATE) &lt; @LASTKEEPDATE
ORDER BY
E.EVENTID ASC

END
ELSE
BEGIN
--client events
IF @PMSTATUS IS null
INSERT #EVENTGROOM
SELECT TOP(@ROWSPERITERATION) e.cseventId
FROM APM.csevent (NOLOCK) AS e
WHERE
e.SEVIEWERDBID = @DATABASEID AND
e.utcDate &lt; @LASTKEEPDATE
ELSE
INSERT #EVENTGROOM
SELECT TOP(@ROWSPERITERATION) e.csEventId
FROM APM.CSEVENT (NOLOCK) E
JOIN apm.PMCLIENTEVENTTRACE (NOLOCK) ET ON E.CSEVENTID = ET.CSEVENTID
JOIN apm.PMTRACE PT (NOLOCK) ON PT.PMTRACEID = ET.PMTRACEID
WHERE
e.PMSTATUS = @PMSTATUS AND
e.utcDate &lt; @LASTKEEPDATE AND
e.SEVIEWERDBID = @DATABASEID
GROUP BY
E.CSEVENTID
HAVING
MAX(PT.UTCDATE) &lt; @LASTKEEPDATE
ORDER BY
E.csEVENTID ASC
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.GroomingWorkTables'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.GroomingWorkTables AS RETURN 1')
END
GO
/* PROCEDURE GROOM SERVER EVENTS, CLIENT EVENTS AND PERFORMANCE COUNTERS. */
/* Description: */
/* The stored proc delete old events and performance counters. It also delete */
/* events with status 'Deleted' or 'By design' using parameters from config table. */
/* INPUT PARAMETERS: */
/* @TABLENAME: */
/* 'Event' - grooming server and client events */
/* 'PerfHourly'- grooming performance counters for the perfhourly table */
/* 'PerfDaily'- grooming performance counters for the perfDaily table */
/* @DATABASEID: database identifier */
/* @RECORDCOUNT: batch record size */
/* @TRACELEVEL: trace level */
alter PROCEDURE [APM].[GroomingWorkTables]
@TABLENAME nvarchar(255),
@RECORDCOUNT INT,
@DATABASEID INT,
@POSTGROOMINGPERIOD INT,
@TRACELEVEL INT
AS
BEGIN
SET NOCOUNT ON;

DECLARE @MESSAGE nvarchar(MAX)
DECLARE @ROWSAFFECTED int
DECLARE @TMPROWSAFFECTED int


DECLARE
@ERRORIND bit
,@ERRORMESSAGE nvarchar(4000)
,@ERRORNUMBER int
,@ERRORSEVERITY int
,@ERRORSTATE int
,@ERRORLINE int
,@ERRORPROCEDURE sysname
,@ERRORMESSAGETEXT nvarchar(4000)

SET @ERRORIND = 0

BEGIN TRY

IF @TRACELEVEL = 4
BEGIN
DECLARE
@PERIODDATESTR nvarchar(20)
SET @PERIODDATESTR = CONVERT(nvarchar(20), DATEADD(Day, -@POSTGROOMINGPERIOD, GETUTCDATE()), 110)
SELECT @MESSAGE = MESSAGE FROM APM.MESSAGES WHERE ID = 50033
RAISERROR (@MESSAGE, 0, 1, @RECORDCOUNT, @POSTGROOMINGPERIOD, @PERIODDATESTR) WITH NOWAIT;
END

CREATE TABLE #EVENTGROOM (
EVENTID BIGINT
)

--clear old events
IF @TABLENAME = N'Event'
BEGIN
-- create event groom settings
DECLARE @EVENTGROOMSETTINGS TABLE
(
id int IDENTITY(1,1)
,configName nvarchar(50) -- configuration parameter
,pmstatus tinyint -- problem management status id
,client bit -- client or server event (1- client, 0 - server)
,defaultLifeTime int -- default life time in hours
)
INSERT @EVENTGROOMSETTINGS(configName, pmstatus, client, defaultLifeTime)
SELECT N'PMLifeTimeInHoursForDeletedEvents' AS configName, 2 AS pmstatus, 0 AS client, 24 AS defaultLifeTime
UNION ALL
SELECT N'PMLifeTimeInHoursForDeletedEvents', 2, 1, 24
UNION ALL
SELECT N'PMLifeTimeInHoursForByDesignEvents', 3, 0, 72
UNION ALL
SELECT N'PMLifeTimeInHoursForByDesignEvents', 3, 1, 72
UNION ALL
SELECT NULL, NULL, 0, NULL
UNION ALL
SELECT NULL, NULL, 1, NULL

DECLARE
@CONFIGNAME nvarchar(50)
,@LASTKEEPDATE datetime
,@CLIENT bit
,@PMSTATUS tinyint
,@LIFETIMEINHOURS int
,@DISPLAYTABLENAME sysname
,@EVENTGROOMSETTINGSID int

-- cycle by event groomsetting
WHILE EXISTS(SELECT * FROM @EVENTGROOMSETTINGS)
BEGIN
--get first settings
SELECT TOP (1)
@EVENTGROOMSETTINGSID = id
,@CONFIGNAME = configName
,@PMSTATUS = pmstatus
,@CLIENT = client
,@LIFETIMEINHOURS = defaultLifeTime
FROM
@EVENTGROOMSETTINGS

--calculate last keep date
SELECT @LASTKEEPDATE = DATEADD(Day, -@POSTGROOMINGPERIOD, GETUTCDATE())
IF @CONFIGNAME IS NOT NULL
BEGIN
SELECT @LIFETIMEINHOURS = CAST(CAST(configvalue AS nvarchar(10)) AS int) FROM APM.CONFIG (NOLOCK)
WHERE configname = @CONFIGNAME
SELECT @LASTKEEPDATE = DATEADD(hh, -@LIFETIMEINHOURS, GETUTCDATE())
END

--trace grooming settings
DECLARE @LASTKEEPDATESTR nvarchar(50)
SELECT @LASTKEEPDATESTR = CONVERT(nvarchar(50), @LASTKEEPDATE, 100)
SELECT @MESSAGE = message FROM APM.MESSAGES (NOLOCK) WHERE id = 50034
RAISERROR (@MESSAGE, 0, 1,
@PMSTATUS, @LIFETIMEINHOURS, @LASTKEEPDATESTR) WITH NOWAIT;

-- execute event grooming
SELECT @ROWSAFFECTED = 0
WHILE 1 = 1
BEGIN
TRUNCATE TABLE #EVENTGROOM
--fill #EVENTGROOM
EXEC APM.ExtractEventGroomingRows
@RECORDCOUNT
,@LASTKEEPDATE
,@DATABASEID
,@CLIENT
,@PMSTATUS
--delete events if #EVENTGROOM is not empty otherwise delete old event groups
EXEC APM.DeleteEventsOrEventGroups
@RECORDCOUNT
,@CLIENT
,@LASTKEEPDATE
,@TMPROWSAFFECTED OUTPUT

IF EXISTS(SELECT * FROM #EVENTGROOM)
-- calculate rows affected
SELECT @ROWSAFFECTED = @TMPROWSAFFECTED + @@ROWCOUNT
ELSE
-- break if #EVENTGROOM is empty
BREAK
END

DELETE @EVENTGROOMSETTINGS WHERE
id = @EVENTGROOMSETTINGSID

----- Trace for events ------
IF @TRACELEVEL = 4
BEGIN
SELECT @DISPLAYTABLENAME = CASE when @CLIENT = 1 THEN N'csEvent' ELSE N'Event' END
SELECT @MESSAGE = MESSAGE FROM APM.MESSAGES WHERE ID = 50023
RAISERROR (@MESSAGE, 0, 1, @ROWSAFFECTED, @DISPLAYTABLENAME) WITH NOWAIT;
END

----- Trace for groups ------
IF @TRACELEVEL = 4
BEGIN
SELECT @DISPLAYTABLENAME = CASE when @CLIENT = 1 THEN N'csEventGroup' ELSE N'EventGroup' END
SELECT @MESSAGE = MESSAGE FROM APM.MESSAGES WHERE ID = 50023
RAISERROR (@MESSAGE, 0, 1, @ROWSAFFECTED, @DISPLAYTABLENAME) WITH NOWAIT;
END
END
END

DROP TABLE #EVENTGROOM

--clear PerfHourly table
IF @TABLENAME = N'PerfHourly'
BEGIN
WHILE EXISTS (SELECT * FROM APM.PerfHourly
WHERE UTCDate &lt; DATEADD(Day, -@POSTGROOMINGPERIOD, GETUTCDATE()))
BEGIN
DELETE TOP(@RECORDCOUNT) FROM APM.PerfHourly
WHERE utcdate &lt; DATEADD(Day, -@POSTGROOMINGPERIOD, GETUTCDATE())
SELECT @ROWSAFFECTED = @ROWSAFFECTED + @@ROWCOUNT
END
IF @TRACELEVEL = 4
BEGIN
SELECT @MESSAGE = MESSAGE FROM APM.MESSAGES WHERE ID = 50023
RAISERROR (@MESSAGE, 0, 1, @ROWSAFFECTED, @TABLENAME) WITH NOWAIT;
END
END

--clear PerfDaily table
IF @TABLENAME = N'PerfDaily'
BEGIN
WHILE EXISTS (SELECT * FROM APM.PerfDaily
WHERE UTCDATE &lt; DATEADD(Day, -@POSTGROOMINGPERIOD, GETUTCDATE()))
BEGIN
DELETE TOP(@RECORDCOUNT) FROM APM.PerfDaily
WHERE UTCDATE &lt; DATEADD(Day, -@POSTGROOMINGPERIOD, GETUTCDATE())
SELECT @ROWSAFFECTED = @ROWSAFFECTED + @@ROWCOUNT
END
IF @TRACELEVEL = 4
BEGIN
SELECT @MESSAGE = MESSAGE FROM APM.MESSAGES WHERE ID = 50023
RAISERROR (@MESSAGE, 0, 1, @ROWSAFFECTED, @TABLENAME) WITH NOWAIT;
END
END

END TRY

BEGIN CATCH
IF (@@TRANCOUNT &gt; 0)
ROLLBACK TRAN

SELECT
@ERRORNUMBER = ERROR_NUMBER()
,@ERRORSEVERITY = ERROR_SEVERITY()
,@ERRORSTATE = ERROR_STATE()
,@ERRORLINE = ERROR_LINE()
,@ERRORPROCEDURE = ISNULL(ERROR_PROCEDURE(), '-')
,@ERRORMESSAGETEXT = ERROR_MESSAGE()

SET @ERRORIND = 1
END CATCH

IF (@ERRORIND = 1)
BEGIN
DECLARE
@ADJUSTEDERRORSEVERITY INT
,@ERROR_MESSAGE nvarchar(max)

SET @ADJUSTEDERRORSEVERITY = CASE
WHEN @ERRORSEVERITY &gt; 18 THEN 18
ELSE @ERRORSEVERITY
END

SELECT @ERROR_MESSAGE = message FROM APM.Messages WHERE id = 50004
RAISERROR (@ERROR_MESSAGE, @ADJUSTEDERRORSEVERITY, 1
,@ERRORNUMBER
,@ERRORSEVERITY
,@ERRORSTATE
,@ERRORPROCEDURE
,@ERRORLINE
,@ERRORMESSAGETEXT
)
END
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.GetOldComputersOrSources'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.GetOldComputersOrSources AS RETURN 1')
END
GO

alter PROCEDURE APM.GetOldComputersOrSources
@ISCOMPUTER bit, @DEBUG bit
AS
BEGIN
SET NOCOUNT ON

DECLARE
@SQL nvarchar(MAX)
,@FROMITEMTABLE nvarchar(1000)
,@FROMPCITEMTABLE nvarchar(1000)
,@EVENTFIELDS nvarchar(1000)
,@PCFIELDS nvarchar(1000)
,@WHEREITEM nvarchar(1000)
,@WHEREPCITEM nvarchar(1000)

SELECT
@EVENTFIELDS = CASE @ISCOMPUTER WHEN 1
THEN N'm.MACHINEID AS Id, m.MACHINE AS ItemName, t.utceventdate AS LastRefreshDate'
ELSE N's.SOURCEID AS Id, s.SOURCE AS ItemName, t.utceventdate AS LastRefreshDate'
END
,@PCFIELDS = CASE @ISCOMPUTER WHEN 1
THEN N'm.MACHINEID AS Id, m.MACHINE AS ItemName, t.utcdate AS LastRefreshDate'
ELSE N's.SOURCEID AS Id, s.SOURCE AS ItemName, t.utcdate AS LastRefreshDate '
END
,@FROMITEMTABLE = CASE @ISCOMPUTER WHEN 1
THEN N'APM.MACHINE m (NOLOCK)'
ELSE N'APM.SOURCE s (NOLOCK)'
END

,@WHEREITEM = CASE @ISCOMPUTER WHEN 1
THEN N'WHERE t.MACHINEID = m.MACHINEID'
ELSE N'WHERE t.SOURCEID = s.SOURCEID'
END

,@SQL = N'

;WITH AllItemsSet AS
(
SELECT {0}
FROM {2}
OUTER APPLY (
SELECT TOP 1 t.UTCEVENTDATE FROM APM.EVENT t (NOLOCK)
{3}
ORDER BY t.UTCEVENTDATE DESC
) t

UNION ALL

SELECT {1}
FROM {2}
OUTER APPLY (
SELECT TOP 1 t.UTCDATE FROM APM.csEVENT t (NOLOCK)
{3}
ORDER BY t.UTCDATE DESC
) t

UNION ALL

SELECT {1}
FROM {2}
OUTER APPLY (
SELECT TOP 1 t.UTCDATE FROM APM.PerfHourly t (NOLOCK)
{3}
ORDER BY t.UTCDATE DESC
) t
)
SELECT 0 AS Checked, Min(Id) AS Id, ItemName, MAX(LastRefreshDate) AS LastRefreshDate
FROM AllItemsSet
GROUP BY
ItemName
ORDER BY
LastRefreshDate
'
SELECT @SQL = REPLACE(@SQL, N'{0}', @EVENTFIELDS)
SELECT @SQL = REPLACE(@SQL, N'{1}', @PCFIELDS)
SELECT @SQL = REPLACE(@SQL, N'{2}', @FROMITEMTABLE)
SELECT @SQL = REPLACE(@SQL, N'{3}', @WHEREITEM)

IF @DEBUG = 1
PRINT @SQL

EXEC sp_executesql @SQL, N''
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.CalculateOldComputersOrSources'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.CalculateOldComputersOrSources AS RETURN 1')
END
GO

alter PROCEDURE APM.CalculateOldComputersOrSources
@ISCOMPUTER bit, @ITEMS nvarchar(MAX), @DEBUG bit, @RECCOUNT int OUTPUT
AS
BEGIN
SET NOCOUNT ON

IF LEN(@ITEMS) = 0
BEGIN
RAISERROR('Parameter @ITEMS is empty.', 16, 1, 'CalculateOldComputersOrSources')
RETURN
END

DECLARE
@SQL nvarchar(MAX)
,@JOINITEMTABLE nvarchar(1000)
,@JOINFILTER nvarchar(1000)

SELECT
@JOINITEMTABLE = CASE @ISCOMPUTER WHEN 1
THEN N'JOIN APM.MACHINE m (NOLOCK) ON m.MachineId = t.MachineId'
ELSE N'JOIN APM.SOURCE s (NOLOCK) ON s.SourceId = t.SourceId'
END
,@JOINFILTER = CASE @ISCOMPUTER WHEN 1
THEN N'JOIN APM.GetMultiParameters(@ITEMS, @EMPTY) f ON f.VALUE = m.MachineId'
ELSE N'JOIN APM.GetMultiParameters(@ITEMS, @EMPTY) f ON f.VALUE = s.SourceId'
END
,@SQL = N'
;WITH AllItemsSet AS
(
SELECT COUNT(t.eventId) AS recCount
FROM APM.EVENT t(NOLOCK)
{0}
{1}

UNION ALL

SELECT COUNT(t.cseventId) AS recCount
FROM APM.csEVENT t(NOLOCK)
{0}
{1}

UNION ALL

SELECT COUNT(t.perfhourlyId) AS recCount
FROM APM.PERFHOURLY t (NOLOCK)
{0}
{1}
UNION ALL

SELECT COUNT(t.perfdailyId) AS recCount
FROM APM.PERFDAILY t (NOLOCK)
{0}
{1}
)
SELECT @RECCOUNT=SUM(recCount) FROM AllItemsSet
'

DECLARE @PARAMS nvarchar(MAX)

SELECT @SQL = REPLACE(@SQL, N'{0}', @JOINITEMTABLE)
SELECT @SQL = REPLACE(@SQL, N'{1}', @JOINFILTER)

IF @DEBUG = 1
PRINT @SQL

SELECT @PARAMS = N'@ITEMS nvarchar(max), @EMPTY nvarchar(10), @RECCOUNT int OUTPUT'

EXEC sp_executesql @SQL, @PARAMS, @ITEMS, N'', @RECCOUNT = @RECCOUNT OUTPUT
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.GroomingOldComputersOrSources'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.GroomingOldComputersOrSources AS RETURN 1')
END
GO

ALTER PROCEDURE [apm].[GroomingOldComputersOrSources]
@ISCOMPUTER BIT,
@DELETEPERITERATION INT,
@DELETEPERREQUEST int,
@ITEMS nvarchar(MAX),
@DEBUG bit,
@DELETEDCOUNT int OUTPUT,
@DONE bit OUTPUT
AS
BEGIN
SET NOCOUNT ON;

DECLARE
@SERVEREVENTDELETED int
,@CLIENTEVENTDELETED int
,@COUNTERDELETED int


IF @DELETEPERITERATION &lt;= 0
BEGIN
RAISERROR('Parameter @DELETEPERITERATION is less or it is equal to zero.', 16, 1, 'GroomingOldComputersOrSources')
RETURN
END

IF @DELETEPERREQUEST &lt;= 0
BEGIN
RAISERROR('Parameter @DELETEPERREQUEST is less or it is equal to zero.', 16, 1, 'GroomingOldComputersOrSources')
RETURN
END

IF @DELETEPERREQUEST &lt; @DELETEPERITERATION
BEGIN
RAISERROR('Parameter @DELETEPERREQUEST should be greater @DELETEPERITERATION parameter.', 16, 1, 'GroomingOldComputersOrSources')
RETURN
END


IF LEN(@ITEMS) = 0
BEGIN
RAISERROR('Parameter @ITEMS is empty.', 16, 1, 'GroomingOldComputersOrSources')
RETURN
END

DECLARE @ROWSAFFECTED INT

DECLARE
@ERRORIND bit
,@ERRORMESSAGE nvarchar(4000)
,@ERRORNUMBER int
,@ERRORSEVERITY int
,@ERRORSTATE int
,@ERRORLINE int
,@ERRORPROCEDURE sysname
,@ERRORMESSAGETEXT nvarchar(4000)

CREATE TABLE #ItemsToDelete
(
[Value] NVARCHAR(255) collate database_default
)

INSERT INTO #ItemsToDelete
SELECT [Value]
FROM APM.GETMULTIPARAMETERS(@ITEMS, N'')

DECLARE
@SQL nvarchar(MAX)
,@JOINITEMTABLE nvarchar(1000)
,@JOINFILTER nvarchar(1000)

SELECT
@JOINITEMTABLE = CASE @ISCOMPUTER WHEN 1
THEN N'JOIN APM.MACHINE m (NOLOCK) ON m.MachineId = t.MachineId'
ELSE N'JOIN APM.SOURCE s (NOLOCK) ON s.SourceId = t.SourceId'
END
,@JOINFILTER = CASE @ISCOMPUTER WHEN 1
THEN N'JOIN #ItemsToDelete AS f ON f.VALUE = m.MachineId'
ELSE N'JOIN #ItemsToDelete AS f ON f.VALUE = s.SourceId'
END

SET @ERRORIND = 0

BEGIN TRY

DECLARE @DELETEHISTORY TABLE (affected int)

--clear client events events and related referencing tables
SELECT @ROWSAFFECTED = 0

CREATE TABLE #EVENTGROOM (
EVENTID INT
)

CREATE TABLE #TMPPROBINGAPPLICATION (APPLICATIONID int)


SELECT @DELETEDCOUNT = 0

WHILE 1 = 1
BEGIN

SELECT @DONE = 1

-- clear iteration result
DELETE @DELETEHISTORY
TRUNCATE TABLE #EVENTGROOM

SELECT @ROWSAFFECTED = 0

SELECT @SQL = N'
INSERT #EVENTGROOM (EVENTID)
SELECT TOP(@DELETEPERITERATION) t.cseventId
FROM APM.csevent t (nolock)
{0}
{1}
'

SELECT @SQL = REPLACE(@SQL, N'{0}', @JOINITEMTABLE)
SELECT @SQL = REPLACE(@SQL, N'{1}', @JOINFILTER)

IF @DEBUG = 1
PRINT @SQL

DECLARE @PARAMS nvarchar(MAX)

SELECT @PARAMS = N'@DELETEPERITERATION int'

EXEC sp_executesql @SQL, @PARAMS, @DELETEPERITERATION

-- Grooming PageEvent-----
DELETE pe
FROM APM.cspageevent AS pe
JOIN #EVENTGROOM AS eventFilter ON pe.cseventid = eventFilter.EVENTID

-- Grooming Peripheral Details -----
DELETE pd
FROM APM.csperipheraldetail AS pd
JOIN APM.csperipheral AS pe ON pe.csperipheralId = pd.csperipheralId
JOIN #EVENTGROOM AS eventFilter ON pe.cseventid = eventFilter.EVENTID

-- Grooming Peripheral ------
DELETE pe
FROM APM.csperipheral AS pe
JOIN #EVENTGROOM AS eventFilter ON pe.cseventid = eventFilter.EVENTID

-- Grooming csHeaviestResource ---
DELETE hr
FROM APM.csHeaviestResource AS hr
JOIN #EVENTGROOM AS eventFilter ON hr.cseventid = eventFilter.EVENTID

-- Grooming ajax events ---
DELETE aj
FROM APM.csAjax AS aj
JOIN #EVENTGROOM AS eventFilter ON aj.cseventid = eventFilter.EVENTID

-- Grooming async ajax events ---
DELETE aj
FROM APM.csAsyncAjax AS aj
JOIN #EVENTGROOM AS eventFilter ON aj.cseventid = eventFilter.EVENTID

-- Grooming async jscript events ---
DELETE js
FROM APM.csJScriptEvent AS js
JOIN #EVENTGROOM AS eventFilter ON js.cseventid = eventFilter.EVENTID

-- Grooming client exception events ---
DELETE ex
FROM APM.csexevent AS ex
JOIN #EVENTGROOM AS eventFilter ON ex.cseventid = eventFilter.EVENTID

-- Grooming client event detail ---
DELETE ed
FROM APM.CSEVENTDETAIL AS ed
JOIN #EVENTGROOM AS eventFilter ON ed.cseventid = eventFilter.EVENTID

-- Grooming client events ---
DELETE ev
FROM APM.csEvent ev
JOIN #EVENTGROOM AS eventFilter ON ev.cseventid = eventFilter.EVENTID

SELECT @ROWSAFFECTED = @@ROWCOUNT

INSERT @DELETEHISTORY(affected) SELECT @ROWSAFFECTED

--- Save deleted client events --
SELECT @CLIENTEVENTDELETED = @ROWSAFFECTED

TRUNCATE TABLE #EVENTGROOM

--clear server events events and related referencing tables
SELECT @SQL = N'
INSERT #EVENTGROOM (EVENTID)
SELECT TOP(@DELETEPERITERATION) t.eventId
FROM APM.event t (nolock)
{0}
{1}
'

SELECT @SQL = REPLACE(@SQL, N'{0}', @JOINITEMTABLE)
SELECT @SQL = REPLACE(@SQL, N'{1}', @JOINFILTER)

IF @DEBUG = 1
PRINT @SQL

SELECT @PARAMS = N'@DELETEPERITERATION int'

EXEC sp_executesql @SQL, @PARAMS, @DELETEPERITERATION

--- Grooming performance node ---------
DELETE pn
FROM APM.PerformanceNode AS pn
JOIN #EVENTGROOM AS eventFilter ON pn.eventid = eventFilter.EVENTID

DELETE rgn
FROM APM.ResourceGroupNode AS rgn
JOIN #EVENTGROOM AS eventFilter ON rgn.eventid = eventFilter.EVENTID

DELETE en
FROM APM.ExceptionNode AS en
JOIN #EVENTGROOM AS eventFilter ON en.eventid = eventFilter.EVENTID

DELETE ed
FROM APM.EVENTDETAIL AS ed
JOIN #EVENTGROOM AS eventFilter ON ed.eventid = eventFilter.EVENTID

DELETE e
FROM APM.Event AS e
JOIN #EVENTGROOM AS eventFilter ON e.eventid = eventFilter.EVENTID

SELECT @ROWSAFFECTED = @@ROWCOUNT

INSERT @DELETEHISTORY(affected) SELECT @ROWSAFFECTED

-- save deleted server events
SELECT @SERVEREVENTDELETED = @ROWSAFFECTED

--clear PerfHourly table

SELECT @SQL = N'
DELETE TOP(@DELETEPERITERATION) t
FROM APM.PerfHourly t
{0}
{1}
SELECT @ROWSAFFECTED = @@ROWCOUNT
'

SELECT @SQL = REPLACE(@SQL, N'{0}', @JOINITEMTABLE)
SELECT @SQL = REPLACE(@SQL, N'{1}', @JOINFILTER)

IF @DEBUG = 1
PRINT @SQL

SELECT @PARAMS = N'@DELETEPERITERATION int, @ROWSAFFECTED int OUTPUT'

EXEC sp_executesql @SQL, @PARAMS, @DELETEPERITERATION, @ROWSAFFECTED = @ROWSAFFECTED OUTPUT

INSERT @DELETEHISTORY(affected) SELECT @ROWSAFFECTED

-- save deleted counters
SELECT @COUNTERDELETED = @ROWSAFFECTED

--clear PerfDaily table

SELECT @SQL = N'
DELETE TOP(@DELETEPERITERATION) t
FROM APM.PerfDaily t
{0}
{1}
SELECT @ROWSAFFECTED = @@ROWCOUNT
'

SELECT @SQL = REPLACE(@SQL, N'{0}', @JOINITEMTABLE)
SELECT @SQL = REPLACE(@SQL, N'{1}', @JOINFILTER)

IF @DEBUG = 1
PRINT @SQL

SELECT @PARAMS = N'@DELETEPERITERATION int, @ROWSAFFECTED int OUTPUT'

EXEC sp_executesql @SQL, @PARAMS, @DELETEPERITERATION, @ROWSAFFECTED = @ROWSAFFECTED OUTPUT

INSERT @DELETEHISTORY(affected) SELECT @ROWSAFFECTED

--clear APPLICATIONSOURCEMACHINE table
TRUNCATE TABLE #TMPPROBINGAPPLICATION

SELECT @SQL = N'
DELETE TOP(@DELETEPERITERATION) t OUTPUT DELETED.ApplicationId INTO #TMPPROBINGAPPLICATION
FROM APM.APPLICATIONSOURCEMACHINE t
{0}
{1}
SELECT @ROWSAFFECTED = @@ROWCOUNT
'

SELECT @SQL = REPLACE(@SQL, N'{0}', @JOINITEMTABLE)
SELECT @SQL = REPLACE(@SQL, N'{1}', @JOINFILTER)

IF @DEBUG = 1
PRINT @SQL

SELECT @PARAMS = N'@DELETEPERITERATION int, @ROWSAFFECTED int OUTPUT'

EXEC sp_executesql @SQL, @PARAMS, @DELETEPERITERATION, @ROWSAFFECTED = @ROWSAFFECTED OUTPUT

INSERT @DELETEHISTORY(affected) SELECT @ROWSAFFECTED

IF EXISTS(SELECT * FROM @DELETEHISTORY WHERE affected = @DELETEPERITERATION)
SELECT @DONE = 0

SELECT @DELETEDCOUNT = @DELETEDCOUNT + @SERVEREVENTDELETED
+ @CLIENTEVENTDELETED + @COUNTERDELETED

------------------- try delete applications ----------
IF @DONE = 1
BEGIN

--clear Resource table

IF @ISCOMPUTER = 0
WHILE EXISTS
(
SELECT * FROM APM.RESOURCE R
JOIN #ItemsToDelete AS f ON f.VALUE = r.sourceId
)
BEGIN
DELETE TOP(@DELETEPERITERATION) r
FROM APM.Resource R
JOIN #ItemsToDelete AS f ON f.VALUE = r.sourceId
END

DELETE A
FROM APM.APPLICATION A
WHERE
EXISTS
(
SELECT * FROM #TMPPROBINGAPPLICATION tmp
WHERE tmp.APPLICATIONID = A.ApplicationId
) AND
NOT EXISTS
(
SELECT * FROM APM.APPLICATIONSOURCEMACHINE l WITH (NOLOCK)
WHERE l.ApplicationId = A.ApplicationId
)

------------------- try delete machines ----------

IF @ISCOMPUTER = 1
DELETE m
FROM APM.MACHINE m
JOIN #ItemsToDelete AS f ON f.VALUE = m.MachineId

------------------- try delete sources ----------

IF @ISCOMPUTER = 0
DELETE s
FROM APM.Source s
JOIN #ItemsToDelete AS f ON f.VALUE = s.SourceId
BREAK
END

--- Check request result
SELECT @DELETEPERREQUEST = @DELETEPERREQUEST - @SERVEREVENTDELETED
- @CLIENTEVENTDELETED - @COUNTERDELETED

IF @DELETEPERREQUEST &lt;= 0
BREAK
END
END TRY

BEGIN CATCH
IF (@@TRANCOUNT &gt; 0)
ROLLBACK TRAN

SELECT
@ERRORNUMBER = ERROR_NUMBER()
,@ERRORSEVERITY = ERROR_SEVERITY()
,@ERRORSTATE = ERROR_STATE()
,@ERRORLINE = ERROR_LINE()
,@ERRORPROCEDURE = ISNULL(ERROR_PROCEDURE(), '-')
,@ERRORMESSAGETEXT = ERROR_MESSAGE()

SET @ERRORIND = 1
END CATCH

IF (@ERRORIND = 1)
BEGIN
DECLARE
@ADJUSTEDERRORSEVERITY INT
,@ERROR_MESSAGE nvarchar(max)

SET @ADJUSTEDERRORSEVERITY = CASE
WHEN @ERRORSEVERITY &gt; 18 THEN 18
ELSE @ERRORSEVERITY
END

SELECT @ERROR_MESSAGE = message FROM APM.Messages WHERE id = 50004
RAISERROR (@ERROR_MESSAGE, @ADJUSTEDERRORSEVERITY, 1
,@ERRORNUMBER
,@ERRORSEVERITY
,@ERRORSTATE
,@ERRORPROCEDURE
,@ERRORLINE
,@ERRORMESSAGETEXT
)
END
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.GetApplicationGroups'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.GetApplicationGroups AS RETURN 1')
END
GO

/**************************************************************************************************/
/* Procedure return application groups */
/**************************************************************************************************/
alter PROCEDURE APM.GetApplicationGroups
AS
BEGIN
SET NOCOUNT ON

SELECT 0 AS Checked, a.APPLICATIONID AS Id, a.APPLICATION AS ItemName
FROM APM.APPLICATION a (NOLOCK)
WHERE a.APPLICATION != 'All'
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.GroomingOldApplicationGroup'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.GroomingOldApplicationGroup AS RETURN 1')
END
GO


/**************************************************************************************************/
/* Procedure delete unused application groups */
/* Parameters: */
/* @ITEM - Application Group */
/**************************************************************************************************/
alter PROCEDURE APM.GroomingOldApplicationGroup
@ITEM int
AS
BEGIN
SET NOCOUNT ON;

IF EXISTS(SELECT * FROM APM.APPLICATION (NOLOCK)
WHERE APPLICATIONID = @ITEM AND APPLICATION = N'All')
BEGIN
RAISERROR('It is forbidden to delete ''All'' aplication group ', 16, 1, 'GroomingOldApplicationGroup')
RETURN
END

DECLARE @ROWSAFFECTED INT

DECLARE
@ERRORIND bit
,@ERRORMESSAGE nvarchar(4000)
,@ERRORNUMBER int
,@ERRORSEVERITY int
,@ERRORSTATE int
,@ERRORLINE int
,@ERRORPROCEDURE sysname
,@ERRORMESSAGETEXT nvarchar(4000)

SET @ERRORIND = 0

BEGIN TRY

DELETE t
FROM APM.APPLICATIONSOURCEMACHINE t
JOIN APM.APPLICATION a (NOLOCK) ON a.APPLICATIONID = T.APPLICATIONID
WHERE
a.ApplicationId = @ITEM

DELETE APM.APPLICATION WHERE APPLICATIONID = @ITEM

END TRY

BEGIN CATCH
IF (@@TRANCOUNT &gt; 0)
ROLLBACK TRAN

SELECT
@ERRORNUMBER = ERROR_NUMBER()
,@ERRORSEVERITY = ERROR_SEVERITY()
,@ERRORSTATE = ERROR_STATE()
,@ERRORLINE = ERROR_LINE()
,@ERRORPROCEDURE = ISNULL(ERROR_PROCEDURE(), '-')
,@ERRORMESSAGETEXT = ERROR_MESSAGE()

SET @ERRORIND = 1
END CATCH

IF (@ERRORIND = 1)
BEGIN
DECLARE
@ADJUSTEDERRORSEVERITY INT
,@ERROR_MESSAGE nvarchar(max)

SET @ADJUSTEDERRORSEVERITY = CASE
WHEN @ERRORSEVERITY &gt; 18 THEN 18
ELSE @ERRORSEVERITY
END

SELECT @ERROR_MESSAGE = message FROM APM.Messages WHERE id = 50004
RAISERROR (@ERROR_MESSAGE, @ADJUSTEDERRORSEVERITY, 1
,@ERRORNUMBER
,@ERRORSEVERITY
,@ERRORSTATE
,@ERRORPROCEDURE
,@ERRORLINE
,@ERRORMESSAGETEXT
)
END
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.ApplicationStatusClient'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.ApplicationStatusClient AS RETURN 1')
END
GO

/****************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: ApplicationStatusClient */
/* USED IN: Application Status Client Report */
/* INPUT PARAMETERS: */
/* @SOURCEIDS - List of the source id, separated by comma. Exp: '1,2,3' */
/* @COMPUTERIDS - List of the computer id, separated by comma. Exp: '1,2,3' */
/* @ENDDATE - End date of the period (in Client timezone) */
/* @PERIOD - Period type(Day, Week or Month). */
/* - Use for the Start Date calculate of the period */
/* @AVERAGEINTERVAL- This value specifies interval, for which average values will */
/* be calculated. Possible values: 1(1 month), 2(2 month), */
/* 3(3 month), 6(6 month), 17 (7 day) */
/* @TRESHOLD - Event duration treshold */
/* @PROBLEM - Event problem type (all, critical) */
/* @INCLUDESUBNET - List masks, which should be included */
/* @EXCLUDESUBNET - List masks, which should be excluded */
/* @WARNINGTHRESHOLD - Threshold specified by user to notify about warning */
/* @ERRORTHRESHOLD - Threshold specified by user to notify about errors */
/* @TIMEZONE - correlate parameter (timezone by min) to return result */
/* in clien timezone */
/****************************************************************************************/

alter PROCEDURE APM.ApplicationStatusClient
@SOURCEIDS NVARCHAR(MAX),
@COMPUTERIDS NVARCHAR(MAX),
@ENDDATE DATETIME,
@PERIOD INT,
@AVERAGEINTERVAL INT,
@THRESHOLD INT,
@PROBLEM NVARCHAR(10),
@INCLUDESUBNET NVARCHAR(MAX),
@EXCLUDESUBNET NVARCHAR(MAX),
@ERRORTHRESHOLD INT,
@WARNINGTHRESHOLD INT,
@TIMEZONE INT,
@PMSTATUS NVARCHAR(50)
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON;

SELECT
@INCLUDESUBNET = REPLACE(@INCLUDESUBNET, N'*', N'%'),
@EXCLUDESUBNET = REPLACE(@EXCLUDESUBNET, N'*', N'%')

/************************************************************************************/
/* Prepare auxiliary variables for the further calculation */
/************************************************************************************/
DECLARE @CLIENTENDDATE DateTime
SET @CLIENTENDDATE = @ENDDATE

--Convert End date to UTC
SET @ENDDATE = DATEADD(minute, -@TIMEZONE, @CLIENTENDDATE)

--Used for counting average value for last three months
DECLARE @PERIODDAYSCOUNT int
SET @PERIODDAYSCOUNT = (CASE
WHEN @PERIOD = 1 THEN 1
WHEN @PERIOD = 2 THEN 7
WHEN @PERIOD = 3 THEN 31
END)

DECLARE @STARTDATE DateTime
SET @STARTDATE = DATEADD(d, -@PERIODDAYSCOUNT, @ENDDATE)

DECLARE @CLIENTSTARTDATE DateTime
SET @CLIENTSTARTDATE = DATEADD(d, -@PERIODDAYSCOUNT, @CLIENTENDDATE)

DECLARE @HOURSCOUNT int
SET @HOURSCOUNT = (CASE
WHEN @PERIOD = 1 THEN 24
WHEN @PERIOD = 2 THEN 24
WHEN @PERIOD = 3 THEN 1 -- Every day of the month have one hour - 00:00
END)

DECLARE @LASTPERIODSTARTDATE DateTime
SET @LASTPERIODSTARTDATE = DATEADD(d, -@PERIODDAYSCOUNT, @STARTDATE)

DECLARE @AVERAGEPERIODSTARTDATE DateTime
SET @AVERAGEPERIODSTARTDATE = (CASE
WHEN @AVERAGEINTERVAL &lt; 10 THEN DATEADD(month, -@AVERAGEINTERVAL, @STARTDATE)
ELSE DATEADD(day, -(@AVERAGEINTERVAL-10), @STARTDATE)
END)

DECLARE @PROCESSORCOUNTERID INT
SELECT @PROCESSORCOUNTERID = PCtypeId FROM apm.PCType (NOLOCK) WHERE type = N'\Process\% Processor Time'

DECLARE @MEMORYCOUNTERID INT
SELECT @MEMORYCOUNTERID = PCtypeId FROM apm.PCType (NOLOCK) WHERE type = N'\Process\Private Bytes'

DECLARE @IOCOUNTERID INT
SELECT @IOCOUNTERID = PCtypeId FROM apm.PCType (NOLOCK) WHERE type = N'\Process\IO Data Bytes/sec'

DECLARE @MONITOREDREQUESTCOUNTERID INT
SELECT @MONITOREDREQUESTCOUNTERID = PCtypeId FROM apm.PCType (NOLOCK) WHERE type = N'\Apps\Monitored Requests'

DECLARE @REQUESTTIMECOUNTERID INT
SELECT @REQUESTTIMECOUNTERID = PCtypeId FROM apm.PCType (NOLOCK) WHERE type = N'\Apps\Avg. Request Time'
/************************************************************************************/
/* ASSISTING TEMP TABLES */
/************************************************************************************/
-- Filter table, which contains machine ids and source ids
-- typeid defines filter type - 1 for source and 2 for machine
-- valueId filter value - source id and machine id
CREATE TABLE #SOURCEMACHINEFILTERTABLE(
TYPEID INT,
VALUEID INT
)

-- Fill table #SOURCEMACHINEFILTERTABLE
INSERT
INTO #SOURCEMACHINEFILTERTABLE
SELECT
p.typeId AS TYPEID,
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@SOURCEIDS, @COMPUTERIDS) AS p

-- Filter table, which contains PM Statuses of Events
CREATE TABLE #PMSTATUSFILTERTABLE(
VALUEID INT
)

-- Fill table #PMSTATUSFILTERTABLE
INSERT
INTO #PMSTATUSFILTERTABLE
SELECT
CAST(p.VALUE AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@PMSTATUS, N'') AS p

-- Filter table for SubnetC values
CREATE TABLE #SUBNETCFILTERTABLE
(
IPID INT,
SUBNETC NVARCHAR(50) collate database_default
)

-- Insert into filter id of the SubnetC to increase performance for event table
INSERT INTO #SUBNETCFILTERTABLE
SELECT DISTINCT
ipid,
SubNetC
FROM
apm.IP AS ip (NOLOCK)
JOIN APM.GetMultiParameters(CASE WHEN LEN(@INCLUDESUBNET) &gt; 0 THEN @INCLUDESUBNET ELSE N'%' END, N'') AS p1 ON (ip.SubnetC LIKE p1.Value)
LEFT OUTER JOIN APM.GetMultiParameters(CASE WHEN LEN(@EXCLUDESUBNET) &gt; 0 THEN @EXCLUDESUBNET ELSE N'Fake' END, N'') AS p2 ON (ip.SubnetC LIKE p2.Value)
WHERE
--Exclude subnets which have correspondance in @EXCLUDESUBNET parameter
p2.typeId IS NULL

-- To form application pool with all sources run in it, it is need to get all sources and its process
CREATE TABLE #PROCESSFORSOURCE
(
SOURCEID INT,
PCPROCESSID INT,
MACHINEID INT,
EXTRAINFO NVARCHAR(255) collate database_default,
PROCESS NVARCHAR(255) collate database_default
)

INSERT INTO #PROCESSFORSOURCE
SELECT
ph.SourceId,
ph.PCProcessId,
ph.MachineId,
COALESCE(p.Extrainfo, N'') AS EXTRAINFO,
--Select process name till # symbol (w3wp#1 -&gt; w3wp, w3wp -&gt; w3wp)
APM.RemoveProcessIdFromName(p.Process) AS Process
FROM
(
SELECT DISTINCT
ph.SourceId,
ph.pcprocessId,
ph.MachineId
FROM
apm.PerfHourly AS ph (NOLOCK)
WHERE
ph.pcprocessId IS NOT NULL
AND ph.UTCDate &gt;= @STARTDATE
AND ph.UTCDate &lt; @ENDDATE
) AS ph
JOIN apm.PCProcess AS p (NOLOCK) ON p.pcprocessId = ph.pcprocessId
JOIN #SOURCEMACHINEFILTERTABLE AS f ON (f.TYPEID = 2 AND ph.MachineId = f.VALUEID)



/************************************************************************************/
/* Main query */
/************************************************************************************/

-- Report frame. It contains all sources, for which values sould be selected,
-- and dates for the specified period (StartDate : EndDate)
;WITH SourcesDates AS
(
SELECT
s.SourceId,
s.source AS source,
s.RowId,
s.IsClient,
-- Select 1, 7 or 31 day from end date in ClientTime zone, without hours.
-- After that add appropriate hours
DATEADD(HOUR, h.n-1, CONVERT(NVARCHAR, DATEADD(d, -d.n, @CLIENTENDDATE), 112)) AS ClientDate
FROM
(SELECT
ROW_NUMBER() OVER(
PARTITION BY
CASE WHEN s.Source like N'%(Client)' THEN 1
ELSE 0
END
ORDER BY
S.Source
) AS RowId,

s.Source,
S.SourceId,
(CASE WHEN s.Source like N'%(Client)' THEN 1
ELSE 0
END ) AS IsClient
FROM
apm.SOURCE AS s
JOIN #SOURCEMACHINEFILTERTABLE AS sourceFilter ON s.SourceId = sourceFilter.VALUEID
WHERE
sourceFilter.TYPEID = 1
) AS S
CROSS JOIN APM.fn_nums(@PERIODDAYSCOUNT) AS d
CROSS JOIN APM.fn_nums(@HOURSCOUNT) AS h
),

-- Get sources name, ids list separated by comma per app pool
-- This info should be selected for all sources, even they are in the same application pool
-- as in this report grouping by source is applied not by application pool.
AppPoolInfo AS
(
SELECT
c.SOURCEID,
c.EXTRAINFO,
c.PROCESS,
-- all source names which have the same process name as passed in @SOURCEIDS
(SELECT A.source AS [data()]
FROM
(
SELECT DISTINCT
N'''' + s.source + N'''' + N',' AS source
FROM
#PROCESSFORSOURCE AS c1
JOIN Source AS s ON c1.SOURCEID = s.SourceId
WHERE
c1.EXTRAINFO = c.EXTRAINFO
AND c1.PROCESS = c.PROCESS
AND c1.MACHINEID = c.MACHINEID
) AS A
FOR XML PATH ('')
) AS AppPoolSources
FROM
#PROCESSFORSOURCE AS c
JOIN #SOURCEMACHINEFILTERTABLE AS f ON (f.TYPEID = 1 AND f.VALUEID = c.SOURCEID)
GROUP BY
c.SOURCEID,
c.MACHINEID,
c.EXTRAINFO,
c.PROCESS
),
--Add Pool name in-front of source list, if it is executable application, then app pool countains source name
PrepareAppPoolInfo AS (
SELECT DISTINCT
CASE
WHEN COALESCE(info.ExtraInfo,'') = '' THEN CASE info.AppPoolSources WHEN '' THEN '' ELSE LEFT(info.AppPoolSources, LEN(info.AppPoolSources)-1) END
ELSE info.ExtraInfo + CASE info.AppPoolSources WHEN '' THEN '' ELSE ' (' + LEFT(info.AppPoolSources, LEN(info.AppPoolSources) - 1) + ')' END
END AppPool,
info.SourceId,
info.ExtraInfo
FROM
AppPoolInfo AS info
),
-- Forms application pool list for each source
-- Format: AppPool1 ('Source1', 'Source2', Source3), AppPool2 ('Source1', 'Source4')
SourceAppPools AS (
SELECT
s.SourceId,
s.Source,
COALESCE((SELECT a.AppPool AS [data()]
FROM
(
SELECT DISTINCT
info.AppPool + N',' AS AppPool
FROM
PrepareAppPoolInfo as info
WHERE
info.Sourceid = s.Sourceid
) AS A
FOR XML PATH ('')
),s.Source + '-') AS AppPoolInfo
FROM
apm.Source AS s
JOIN #SOURCEMACHINEFILTERTABLE AS f ON (f.TYPEID = 1 AND f.VALUEID = s.SourceId)
),
--Prepares and filters server events for further manipulations
ApplicationStatusClient_EventsFiltered AS
(
SELECT
e.sourceid,
e.eventid,
-- this field is need to determine number of days when
-- there were some events in DB. If number of days is less than 7,
-- then it is supposed that average valu is not correct enought
DATEDIFF(DAY, DATEADD(mi, @TIMEZONE, e.utceventdate), @CLIENTSTARTDATE) AS EventFillFactor,
--Removing APM.GetDatePart replacing the execution by the code below.
--It boosts the overall performance as it reduces the number of calls of scalar function
CASE @PERIOD
WHEN 3 THEN CONVERT(NVARCHAR, DATEADD(mi, @TIMEZONE, e.utceventdate), 112)
ELSE DATEADD(hh,
DATEPART(hh, DATEADD(mi, CAST(@TIMEZONE AS int), e.utceventdate)),
CONVERT(NVARCHAR, DATEADD(mi, @TIMEZONE, e.utceventdate), 112))
END as Date,
--hour is taken as DateDifference in day between 05/04/2009 9:00AM and 05/03/2009 9:00PM is one day,
--despite in case of @PERIOD = 'Day' it can be interpretated as one day (if 05/04/2009 9:00AM is end date), so difference should be taken as 0
(DATEDIFF(hour, e.utceventdate, @ENDDATE)-1) / (@PERIODDAYSCOUNT*24) AS PeriodId
FROM
apm.Event AS e (NOLOCK)
JOIN #SOURCEMACHINEFILTERTABLE AS f1 ON (f1.VALUEID = e.sourceid and f1.TYPEID = 1)
JOIN #SOURCEMACHINEFILTERTABLE AS f2 ON (f2.VALUEID = e.machineid and f2.TYPEID = 2)
JOIN #PMSTATUSFILTERTABLE AS f3 ON (f3.VALUEID = e.PMStatus)
WHERE
((e.EventClassType = N'Performance' AND e.eventduration/1000000.0 &gt;= @THRESHOLD )
OR e.EventClassType = N'exception')
AND (e.category LIKE @PROBLEM OR e.category IS NULL)
AND e.utceventdate &gt;= @AVERAGEPERIODSTARTDATE
AND e.utceventdate &lt; @ENDDATE
),
PrepareEventsServerAvg AS
(
SELECT
e.sourceid AS sourceid,
e.PeriodId,
-- PeriodId is 0 for the current period, 1 for last and 1..n for average
-- This manipulation should shift Client date to current period for
-- other periods - average and last. Client date is in client time zone
DATEADD(day, e.PeriodId*@PERIODDAYSCOUNT, e.Date) AS ClientDate,
MAX(EventFillFactor) AS EventFillFactor,
COUNT(CASE WHEN e.PeriodId = 0 THEN eventid END) AS CurrentEventsCount,
COUNT(CASE WHEN e.PeriodId = 1 THEN eventid END) AS LastEventsCount,
COUNT(CASE WHEN PeriodId &gt; 0 THEN eventid END) AS AvgEventsCount
FROM
ApplicationStatusClient_EventsFiltered AS e
GROUP BY
e.SourceId,
e.PeriodId,
e.Date
),
EventsServer AS
(
SELECT
e.sourceid AS sourceid,
e.ClientDate,
MAX(EventFillFactor) AS EventFillFactor,
MAX(CurrentEventsCount) AS CurrentEventsCount,
MAX(LastEventsCount) AS LastEventsCount,
AVG(CASE WHEN PeriodId &gt; 0 THEN AvgEventsCount*1.0 END) AS AvgEventsCount
FROM
PrepareEventsServerAvg AS e
GROUP BY
sourceid,
e.ClientDate
),

/****************************************************************************************************************/
/* Section selects client events */
/****************************************************************************************************************/
-- Select Client Side events
ApplicationStatusClient_ClientEventsFiltered AS
(
SELECT
e.SourceId,
e.CSEventId AS EventId,
-- this field is need to determine number of days when
-- there were some events in DB. If number of days is less than 7,
-- then it is supposed that average value is not correct enought
DATEDIFF(DAY, DATEADD(mi, @TIMEZONE, e.utcdate), @CLIENTSTARTDATE) AS EventFillFactor,
-- If specified period is Month then take only date part
-- In other cases round date to hours, without minutes and seconds
CASE @PERIOD
WHEN 3 THEN CONVERT(NVARCHAR, DATEADD(mi, @TIMEZONE, e.utcdate), 112)
ELSE DATEADD(hh,
DATEPART(hh, DATEADD(mi, CAST(@TIMEZONE AS int), e.utcdate)),
CONVERT(NVARCHAR, DATEADD(mi, @TIMEZONE, e.utcdate), 112))
END as Date,
--hour is taken as DateDifference in day between 05/04/2009 9:00AM and 05/03/2009 9:00PM is one day,
--despite in case of @PERIOD = 'Day' it can be interpretated as one day (if 05/04/2009 9:00AM is end date), so difference should be taken as 0
(DATEDIFF(hour, e.utcdate, @ENDDATE)- 1) / (@PERIODDAYSCOUNT*24) AS PeriodId
FROM
apm.CSEvent AS e (NOLOCK)
JOIN #SOURCEMACHINEFILTERTABLE AS f1 ON (f1.VALUEID = e.sourceid and f1.TYPEID = 1)
JOIN #SOURCEMACHINEFILTERTABLE AS f2 ON (f2.VALUEID = e.machineid and f2.TYPEID = 2)
JOIN #SUBNETCFILTERTABLE AS f3 ON e.ipid = f3.IPID
JOIN #PMSTATUSFILTERTABLE AS f4 ON (f4.VALUEID = e.PMStatus)
WHERE
e.utcdate &gt;= @AVERAGEPERIODSTARTDATE
AND e.utcdate &lt; @ENDDATE
AND e.PageUri IS NOT NULL
AND (e.ClassType = N'exception' OR e.TotalTime/1000.0 &gt;= @THRESHOLD)
),
-- Group by date (rounded in previous step) and count events
PrepareEventsClientAvg AS
(
SELECT
e.sourceid AS sourceid,
e.PeriodId,
DATEADD(day, e.PeriodId*@PERIODDAYSCOUNT, e.Date) AS ClientDate,
MAX(EventFillFactor) AS EventFillFactor,
COUNT(CASE WHEN e.PeriodId = 0 THEN eventid END) AS CurrentEventsCount,
COUNT(CASE WHEN e.PeriodId = 1 THEN eventid END) AS LastEventsCount,
COUNT(CASE WHEN PeriodId &gt; 0 THEN eventid END) AS AvgEventsCount
FROM
ApplicationStatusClient_ClientEventsFiltered AS e
GROUP BY
e.SourceId,
e.PeriodId,
e.[Date]
),
-- This step is meaningful only for average period AS all events are averaged between "average" period days
EventsClient AS
(
SELECT
e.sourceid AS sourceid,
e.ClientDate,
MAX(EventFillFactor) AS EventFillFactor,
MAX(CurrentEventsCount) AS CurrentEventsCount,
MAX(LastEventsCount) AS LastEventsCount,
AVG(CASE WHEN PeriodId &gt; 0 THEN AvgEventsCount*1.0 END) AS AvgEventsCount
FROM
PrepareEventsClientAvg AS e
GROUP BY
e.SourceId,
e.ClientDate
),
/*************************************************************************************/
/* Activity pcounter queries */
/************************************************************************************/
-- Select Pcounters with specified filtering for activity statistics
ApplicationStatusActivityPerHour AS
(
SELECT
ph.MachineId,
ph.SourceId,
-- this field is need to determine number of days when
-- there were some pc in DB. If number of days is less than 7,
-- then it is supposed that average valu is not correct enought
DATEDIFF(DAY, DATEADD(mi, @TIMEZONE, ph.UTCDate), @CLIENTSTARTDATE) AS ActivityPCFillFactor,
CASE @PERIOD
WHEN 3 THEN CONVERT(NVARCHAR, DATEADD(mi, @TIMEZONE, ph.UTCDate), 112)
ELSE DATEADD(mi, CAST(@TIMEZONE AS int), ph.UTCDate)
END as ClientDate,
(CASE WHEN ph.PCTypeId = @MONITOREDREQUESTCOUNTERID THEN ph.SumValue END) AS MonRequest,
(CASE WHEN ph.PCTypeId = @REQUESTTIMECOUNTERID THEN ph.SumValue / ph.SampleCount END) AS RequestTime,
(DATEDIFF(hour, ph.utcdate, @ENDDATE) - 1) / (@PERIODDAYSCOUNT*24) AS PeriodId
FROM
apm.PerfHourly AS ph (NOLOCK)
JOIN #SOURCEMACHINEFILTERTABLE AS f1 ON (f1.TYPEID = 1 AND ph.SourceId = f1.VALUEID)
JOIN #SOURCEMACHINEFILTERTABLE AS f2 ON (f2.TYPEID = 2 AND f2.VALUEID = ph.MachineId)
WHERE
ph.UTCDate &gt;= @AVERAGEPERIODSTARTDATE
AND ph.UTCDate &lt; @ENDDATE
AND ph.PCTypeID IN (@REQUESTTIMECOUNTERID, @MONITOREDREQUESTCOUNTERID)
),
-- Next step aggregates data only then period is one month.
-- After this step data are aggregated by days.
-- For other periods this step is only pivots data by periods.
ApplicationStatusActivityByDay AS
(
SELECT
MachineId,
SourceId,
PeriodId,
MAX(ActivityPCFillFactor) AS ActivityPCFillFactor,
DATEADD(day, PeriodId*@PERIODDAYSCOUNT, ClientDate) AS ClientDate,
SUM(CASE WHEN PeriodId = 0 THEN MonRequest END) AS CurrentRequestCount,
SUM(CASE WHEN PeriodId = 1 THEN MonRequest END) AS LastRequestCount,
SUM(CASE WHEN PeriodId &gt; 0 THEN MonRequest END) AS AvgRequestCount,
AVG(CASE WHEN PeriodId = 0 THEN RequestTime END) AS CurrentRequestTime,
AVG(CASE WHEN PeriodId = 1 THEN RequestTime END) AS LastRequestTime,
AVG(CASE WHEN PeriodId &gt; 0 THEN RequestTime END) AS AvgRequestTime
FROM
ApplicationStatusActivityPerHour
GROUP BY
MachineId,
SourceId,
PeriodId,
ClientDate
),
-- This step is meaningful only for average period AS all counters are averaged between "average" period dates
ApplicationStatusActivityByPeriod AS
(
SELECT
MachineId,
SourceId,
ClientDate,
MAX(ActivityPCFillFactor) AS ActivityPCFillFactor,
MAX(CurrentRequestCount) AS CurrentRequestCount,
MAX(LastRequestCount) AS LastRequestCount,
AVG(CASE WHEN PeriodId &gt; 0 THEN AvgRequestCount*1.0 END) AS AvgRequestCount,
MAX(CurrentRequestTime) AS CurrentRequestTime,
MAX(LastRequestTime) AS LastRequestTime,
AVG(CASE WHEN PeriodId &gt; 0 THEN AvgRequestTime END) AS AvgRequestTime
FROM
ApplicationStatusActivityByDay
GROUP BY
MachineId,
SourceId,
ClientDate
),
--Aggregate data between machines
ApplicationStatusActivityBySource AS
(
SELECT
SourceId,
ClientDate,
MAX(ActivityPCFillFactor) AS ActivityPCFillFactor,
SUM(CurrentRequestCount) AS CurrentRequestCount,
SUM(LastRequestCount) AS LastRequestCount,
SUM(AvgRequestCount) AS AvgRequestCount,
AVG(CurrentRequestTime) AS CurrentRequestTime,
AVG(LastRequestTime) AS LastRequestTime,
AVG(AvgRequestTime) AS AvgRequestTime
FROM
ApplicationStatusActivityByPeriod
GROUP BY
SourceId,
ClientDate
),
/************************************************************************************/
/* Resources pcounter queries */
/************************************************************************************/
-- Filter resource counters
ApplicationStatusResourcesPerHour AS
(
SELECT
ph.MachineId,
ph.SourceId,
-- this field is need to determine number of days when
-- there were some pc in DB. If number of days is less than 7,
-- then it is supposed that average valu is not correct enought
DATEDIFF(DAY, DATEADD(mi, @TIMEZONE, ph.UTCDate), @CLIENTSTARTDATE) AS ResourcePCFillFactor,
CASE @PERIOD
WHEN 3 THEN CONVERT(NVARCHAR, DATEADD(mi, @TIMEZONE, ph.UTCDate), 112)
ELSE DATEADD(mi, CAST(@TIMEZONE AS int), ph.UTCDate)
END as ClientDate,
(CASE WHEN ph.PCTypeId = @PROCESSORCOUNTERID THEN SUM(ph.SumValue)/SUM(ph.SampleCount) END) AS CPUUsage,
(CASE WHEN ph.PCTypeId = @IOCOUNTERID THEN SUM(ph.SumValue)/SUM(ph.SampleCount) END) AS IOUsage,
(CASE WHEN ph.PCTypeId = @MEMORYCOUNTERID THEN SUM(ph.SumValue)/SUM(ph.SampleCount) END) AS MemoryUsage,
(DATEDIFF(hour, ph.utcdate, @ENDDATE)-1) / (@PERIODDAYSCOUNT*24) AS PeriodId
FROM
apm.PerfHourly AS ph (NOLOCK)
JOIN #SOURCEMACHINEFILTERTABLE AS f1 ON (f1.TYPEID = 1 AND ph.SourceId = f1.VALUEID)
JOIN #SOURCEMACHINEFILTERTABLE AS f2 ON (f2.TYPEID = 2 AND f2.VALUEID = ph.MachineId)
WHERE
ph.UTCDate &gt;= @AVERAGEPERIODSTARTDATE
AND ph.UTCDate &lt; @ENDDATE
AND ph.PCTypeID IN (@PROCESSORCOUNTERID, @IOCOUNTERID, @MEMORYCOUNTERID)
GROUP BY
ph.UTCDate,
ph.PCTypeId,
ph.MachineId,
ph.SourceId
),
-- Group resources by date defined by user. For Period = Week and day this step only devides data by period
ApplicationStatusResourcesByDay AS
(
SELECT
MachineId,
SourceId,
PeriodId,
MAX(ResourcePCFillFactor) AS ResourcePCFillFactor,
DATEADD(day, PeriodId*@PERIODDAYSCOUNT, ClientDate) AS ClientDate,
AVG(CASE WHEN PeriodId = 0 THEN CPUUsage END) AS CurrentCPUUsage,
AVG(CASE WHEN PeriodId = 1 THEN CPUUsage END) AS LastCPUUsage,
AVG(CASE WHEN PeriodId &gt; 0 THEN CPUUsage END) AS AvgCPUUsage,
AVG(CASE WHEN PeriodId = 0 THEN IOUsage END) AS CurrentIOUsage,
AVG(CASE WHEN PeriodId = 1 THEN IOUsage END) AS LastIOUsage,
AVG(CASE WHEN PeriodId &gt; 0 THEN IOUsage END) AS AvgIOUsage,
AVG(CASE WHEN PeriodId = 0 THEN MemoryUsage END) AS CurrentMemoryUsage,
AVG(CASE WHEN PeriodId = 1 THEN MemoryUsage END) AS LastMemoryUsage,
AVG(CASE WHEN PeriodId &gt; 0 THEN MemoryUsage END) AS AvgMemoryUsage
FROM
ApplicationStatusResourcesPerHour
GROUP BY
MachineId,
SourceId,
PeriodId,
ClientDate
),
--This step aggregates data for "average" period, for other periods it is meaningful
ApplicationStatusResourcesByPeriod AS
(
SELECT
SourceId,
ClientDate,
MAX(ResourcePCFillFactor) AS ResourcePCFillFactor,
MAX(CurrentCPUUsage/ COALESCE(m.CPUCount, 1)) AS CurrentCPUUsage,
MAX(LastCPUUsage/ COALESCE(m.CPUCount, 1)) AS LastCPUUsage,
AVG(CASE WHEN PeriodId &gt; 0 THEN AvgCPUUsage/ COALESCE(m.CPUCount, 1) END) AS AvgCPUUsage,
MAX(CurrentIOUsage) AS CurrentIOUsage,
MAX(LastIOUsage) AS LastIOUsage,
AVG(CASE WHEN PeriodId &gt; 0 THEN AvgIOUsage END) AS AvgIOUsage,
MAX(CurrentMemoryUsage) AS CurrentMemoryUsage,
MAX(LastMemoryUsage) AS LastMemoryUsage,
AVG(CASE WHEN PeriodId &gt; 0 THEN AvgMemoryUsage END) AS AvgMemoryUsage
FROM
ApplicationStatusResourcesByDay AS r
JOIN apm.Machine AS m ON m.MachineId = r.MachineId
GROUP BY
r.MachineId,
SourceId,
ClientDate
),
-- Aggregate values between machines
ApplicationStatusResourcesBySource AS
(
SELECT
SourceId,
ClientDate,
MAX(ResourcePCFillFactor) AS ResourcePCFillFactor,
AVG(CurrentCPUUsage) AS CurrentCPUUsage,
AVG(LastCPUUsage) AS LastCPUUsage,
AVG(AvgCPUUsage) AS AvgCPUUsage,
AVG(CurrentIOUsage) AS CurrentIOUsage,
AVG(LastIOUsage) AS LastIOUsage,
AVG(AvgIOUsage) AS AvgIOUsage,
AVG(CurrentMemoryUsage) AS CurrentMemoryUsage,
AVG(LastMemoryUsage) AS LastMemoryUsage,
AVG(AvgMemoryUsage) AS AvgMemoryUsage
FROM
ApplicationStatusResourcesByPeriod
GROUP BY
SourceId,
ClientDate
),
--Check if for some of the machines cpu count is not defined
MachineCPUUndefinedFlag AS
(
SELECT
sf.SOURCEID,
MIN(COALESCE(m.CPUCount, -1)) AS CPUUndefinedFlag
FROM
#PROCESSFORSOURCE AS sf
JOIN apm.Machine AS m (NOLOCK) ON sf.MACHINEID = m.MachineId
GROUP BY
sf.SOURCEID
),
--Combine all data together
CombinedData AS
(
SELECT
SourcesDates.RowId AS RowId,
SourcesDates.IsClient,
SourcesDates.ClientDate,
SourcesDates.Source,
SourcesDates.SourceId,
AppPool.AppPoolInfo,
rpc.CurrentCPUUsage,
rpc.LastCPUUsage,
rpc.AvgCPUUsage,
MAX(rpc.ResourcePCFillFactor) OVER(PARTITION BY SourcesDates.SourceId) AS ResourcePCFillFactor,
(CASE WHEN COALESCE(rpc.AvgCPUUsage, 0) &gt; 0
THEN
ABS(COALESCE(rpc.CurrentCPUUsage,0) - COALESCE(rpc.AvgCPUUsage, 0))*1.0/rpc.AvgCPUUsage
ELSE 0
END) AS CpuStatus,
rpc.CurrentIOUsage/(1024.0) AS CurrentIOUsage,
rpc.LastIOUsage/(1024.0) AS LastIOUsage,
rpc.AvgIOUsage/(1024.0) AS AvgIOUsage,
(CASE WHEN COALESCE(rpc.AvgIOUsage, 0) &gt; 0
THEN
ABS(COALESCE(rpc.CurrentIOUsage,0) - COALESCE(rpc.AvgIOUsage, 0))*1.0/rpc.AvgIOUsage
ELSE 0
END) AS IOStatus,
rpc.CurrentMemoryUsage/(1024.0*1024) AS CurrentMemoryUsage,
rpc.LastMemoryUsage/(1024.0*1024) AS LastMemoryUsage,
rpc.AvgMemoryUsage/(1024.0*1024) AS AvgMemoryUsage,
(CASE WHEN COALESCE(rpc.AvgMemoryUsage, 0) &gt; 0
THEN
ABS(COALESCE(rpc.CurrentMemoryUsage,0) - COALESCE(rpc.AvgMemoryUsage, 0))*1.0/rpc.AvgMemoryUsage
ELSE 0
END) AS MemoryStatus,
MAX(apc.ActivityPCFillFactor) OVER(PARTITION BY SourcesDates.SourceId) AS ActivityPCFillFactor,
apc.CurrentRequestCount,
apc.LastRequestCount,
apc.AvgRequestCount,
(CASE WHEN COALESCE(apc.AvgRequestCount, 0) &gt; 0
THEN
ABS(COALESCE(apc.CurrentRequestCount,0) - COALESCE(apc.AvgRequestCount, 0))*1.0/apc.AvgRequestCount
ELSE 0
END) AS RequestStatus,
apc.CurrentRequestTime/1000.0 AS CurrentRequestTime,
apc.LastRequestTime/1000.0 AS LastRequestTime,
apc.AvgRequestTime/1000.0 AS AvgRequestTime,
(CASE WHEN COALESCE(apc.AvgRequestTime, 0) &gt; 0
THEN
ABS(COALESCE(apc.CurrentRequestTime,0) - COALESCE(apc.AvgRequestTime, 0))*1.0/apc.AvgRequestTime
ELSE 0
END) AS RequestTimeStatus,
MAX(COALESCE(E.EventFillFactor, cs.EventFillFactor)) OVER(PARTITION BY SourcesDates.SourceId) AS EventFillFactor,
COALESCE(E.CurrentEventsCount, cs.CurrentEventsCount) AS CurrentEventsCount,
COALESCE(E.LastEventsCount, cs.LastEventsCount) AS LastEventsCount,
COALESCE(E.AvgEventsCount, cs.AvgEventsCount) AS AvgEventsCount,
(CASE WHEN COALESCE(COALESCE(E.AvgEventsCount, cs.AvgEventsCount), 0) &gt; 0
THEN
ABS(COALESCE(COALESCE(E.CurrentEventsCount, cs.CurrentEventsCount),0) - COALESCE(COALESCE(E.AvgEventsCount, cs.AvgEventsCount), 0))*1.0/COALESCE(E.AvgEventsCount, cs.AvgEventsCount)
ELSE 0
END) AS EventStatus
FROM
SourcesDates
JOIN SourceAppPools AS AppPool ON (AppPool.Sourceid = SourcesDates.Sourceid)
LEFT OUTER JOIN MachineCPUUndefinedFlag AS cpuFlag ON SourcesDates.Sourceid = cpuFlag.Sourceid
LEFT OUTER JOIN ApplicationStatusResourcesBySource AS rpc ON (rpc.ClientDate = SourcesDates.ClientDate AND rpc.SourceId = SourcesDates.Sourceid)
LEFT OUTER JOIN ApplicationStatusActivityBySource AS apc ON (apc.ClientDate = SourcesDates.ClientDate AND apc.SourceId = SourcesDates.Sourceid)
LEFT OUTER JOIN EventsServer AS e ON (e.ClientDate = SourcesDates.ClientDate AND e.SourceId = SourcesDates.Sourceid)
LEFT OUTER JOIN EventsClient AS cs ON (cs.ClientDate = SourcesDates.ClientDate AND cs.SourceId = SourcesDates.Sourceid)

)
SELECT
RowId,
IsClient,
ClientDate,
Source,
SourceId,
AppPoolInfo,
CurrentCPUUsage,
LastCPUUsage,
AvgCPUUsage,
-- If resource counters are presents not more than for 7 day, then don't show threshold message
(CASE WHEN CpuStatus*100 &gt;= @WARNINGTHRESHOLD AND ResourcePCFillFactor &gt;= 7 THEN ClientDate END) AS CPUWarningDate,
(CASE WHEN CpuStatus*100 &gt;= @ERRORTHRESHOLD AND ResourcePCFillFactor &gt;= 7 THEN ClientDate END) AS CPUErrorDate,
CurrentIOUsage,
LastIOUsage,
AvgIOUsage,
-- If resource counters are presents not more than for 7 day, then don't show threshold message
(CASE WHEN IOStatus*100 &gt;= @WARNINGTHRESHOLD AND ResourcePCFillFactor &gt;= 7 THEN ClientDate END) AS IOWarningDate,
(CASE WHEN IOStatus*100 &gt;= @ERRORTHRESHOLD AND ResourcePCFillFactor &gt;= 7 THEN ClientDate END) AS IOErrorDate,
CurrentMemoryUsage,
LastMemoryUsage,
AvgMemoryUsage,
-- If resource counters are presents not more than for 7 day, then don't show threshold message
(CASE WHEN MemoryStatus*100 &gt;= @WARNINGTHRESHOLD AND ResourcePCFillFactor &gt;= 7 THEN ClientDate END) AS MemoryWarningDate,
(CASE WHEN MemoryStatus*100 &gt;= @ERRORTHRESHOLD AND ResourcePCFillFactor &gt;= 7 THEN ClientDate END) AS MemoryErrorDate,
CurrentRequestCount,
LastRequestCount,
AvgRequestCount,
-- If activity counters are presents not more than for 7 day, then don't show threshold message
(CASE WHEN RequestStatus*100 &gt;= @WARNINGTHRESHOLD AND ActivityPCFillFactor &gt;= 7 THEN ClientDate END) AS RequestWarningDate,
(CASE WHEN RequestStatus*100 &gt;= @ERRORTHRESHOLD AND ActivityPCFillFactor &gt;= 7 THEN ClientDate END) AS RequestErrorDate,
CurrentRequestTime,
LastRequestTime,
AvgRequestTime,
-- If activity counters are presents not more than for 7 day, then don't show threshold message
(CASE WHEN RequestTimeStatus*100 &gt;= @WARNINGTHRESHOLD AND ActivityPCFillFactor &gt;= 7 THEN ClientDate END) AS RequestTimeWarningDate,
(CASE WHEN RequestTimeStatus*100 &gt;= @ERRORTHRESHOLD AND ActivityPCFillFactor &gt;= 7 THEN ClientDate END) AS RequestTimeErrorDate,
CurrentEventsCount,
LastEventsCount,
AvgEventsCount,
-- If events are presents not more than for 7 day, then don't show threshold message
(CASE WHEN EventStatus*100 &gt;= @WARNINGTHRESHOLD AND EventFillFactor &gt;= 7 THEN ClientDate END) AS EventWarningDate,
(CASE WHEN EventStatus*100 &gt;= @ERRORTHRESHOLD AND EventFillFactor &gt;= 7 THEN ClientDate END) AS EventErrorDate,
EventStatus,
EventFillFactor,
ActivityPCFillFactor,
ResourcePCFillFactor
FROM
CombinedData
ORDER BY
RowId,
IsClient,
ClientDate
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.ApplicationStatusClientFrequentCSMEvents'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.ApplicationStatusClientFrequentCSMEvents AS RETURN 1')
END
GO

/****************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: ApplicationStatusClientFrequentCSMEvents */
/* USED IN: Application Status Client Report, top 10 Most frequent events */
/* INPUT PARAMETERS: */
/* @SOURCEID - Source id */
/* @COMPUTERIDS - List of the computer id, separated by comma. Exp: '1,2,3' */
/* @ENDDATE - End date of the period (in Client timezone) */
/* @PERIOD - Period type(Day, Week or Month). */
/* - Use for the Start Date calculate of the period */
/* @TRESHOLD - Event duration treshold */
/* @PROBLEM - Event problem type (all, critical) */
/* @INCLUDESUBNET - List masks, which should be included */
/* @EXCLUDESUBNET - List masks, which should be excluded */
/* @TIMEZONE - correlate parameter (timezone by min) to return result */
/* in clien timezone */
/****************************************************************************************/
alter PROCEDURE APM.ApplicationStatusClientFrequentCSMEvents
@SOURCEID INT,
@COMPUTERS NVARCHAR(MAX),
@ENDDATE DATETIME,
@PERIOD INT,
@THRESHOLD DECIMAL(35,0),
@PROBLEM NVARCHAR(10),
@INCLUDESUBNET NVARCHAR(MAX),
@EXCLUDESUBNET NVARCHAR(MAX),
@TIMEZONE INT,
@PMSTATUS NVARCHAR(50)
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON;

SELECT
@INCLUDESUBNET = REPLACE(@INCLUDESUBNET, N'*', N'%'),
@EXCLUDESUBNET = REPLACE(@EXCLUDESUBNET, N'*', N'%')

SET @ENDDATE = DATEADD(minute, -@TIMEZONE, @ENDDATE)

DECLARE @STARTDATE DATETIME
SET @STARTDATE = DATEADD(d, -APM.GetQueryDateCount(@PERIOD, @ENDDATE), @ENDDATE)

DECLARE @LASTPERIODSTARTDATE DateTime
SET @LASTPERIODSTARTDATE = DATEADD(d, -APM.GetQueryDateCount(@PERIOD, @STARTDATE), @STARTDATE)

CREATE TABLE #APPLICATIONSTATUSCLIENT_MACHINE
(
MACHINEID int
)

INSERT
INTO #APPLICATIONSTATUSCLIENT_MACHINE
SELECT
p.value
FROM APM.GetMultiParameters(@COMPUTERS, N'') p

-- Filter table, which contains PM Statuses of Events
CREATE TABLE #PMSTATUSFILTERTABLE(
VALUEID INT
)

-- Fill table #PMSTATUSFILTERTABLE
INSERT
INTO #PMSTATUSFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@PMSTATUS, N'') AS p

-- Filter table for SubnetC values
CREATE TABLE #SUBNETCFILTERTABLE
(
IPID INT,
SUBNETC NVARCHAR(50) collate database_default
)

-- Insert into filter id of the SubnetC to increase performance for event table
INSERT INTO #SUBNETCFILTERTABLE
SELECT DISTINCT
ipid,
SubNetC
FROM
apm.IP AS ip (NOLOCK)
JOIN APM.GetMultiParameters(CASE WHEN LEN(@INCLUDESUBNET) &gt; 0 THEN @INCLUDESUBNET ELSE N'%' END, N'') AS p1 ON (ip.SubnetC LIKE p1.Value)
LEFT OUTER JOIN APM.GetMultiParameters(CASE WHEN LEN(@EXCLUDESUBNET) &gt; 0 THEN @EXCLUDESUBNET ELSE N'Fake' END, N'') AS p2 ON (ip.SubnetC LIKE p2.Value)
WHERE
--Exclude subnets which have correspondance in @EXCLUDESUBNET parameter
p2.typeId IS NULL

;WITH BaseDataSet AS
(
SELECT
eg.[Description],
e.ClassType,
COUNT(CASE WHEN e.utcdate &gt;= @STARTDATE THEN e.cseventid END) as IssuesCount,
COUNT(CASE WHEN e.utcdate &lt; @STARTDATE THEN e.cseventid END) AS LastIssuesCount
FROM
apm.CSEvent (NOLOCK) AS e
JOIN apm.CSEventGroup (NOLOCK) AS eg ON e.csEventGroupId = eg.csEventGroupId
JOIN #APPLICATIONSTATUSCLIENT_MACHINE AS f ON f.MACHINEID = e.MachineId
JOIN #SUBNETCFILTERTABLE AS f1 ON e.ipid = f1.IPID
JOIN #PMSTATUSFILTERTABLE AS f2 ON (f2.VALUEID = e.PMStatus)
WHERE
e.sourceid = @SOURCEID
AND e.utcdate &gt;= @LASTPERIODSTARTDATE
AND e.utcdate &lt; @ENDDATE
AND e.PageUri IS NOT NULL
AND (e.ClassType = N'exception' OR e.TotalTime/1000.0 &gt;= @THRESHOLD)
GROUP BY
eg.Description,
e.ClassType
)

SELECT TOP(10)
ROW_NUMBER() OVER (ORDER BY e.IssuesCount DESC, e.description) AS Id,
e.IssuesCount,
e.LastIssuesCount,
e.Description,
e.ClassType,
COUNT(CASE WHEN e.IssuesCount &gt; 0 THEN 1 ELSE NULL END) OVER() AS TotalCurrentProblemCount,
COUNT(CASE WHEN e.LastIssuesCount &gt; 0 THEN 1 ELSE NULL END) OVER() AS TotalLastProblemCount,
SUM(e.IssuesCount) OVER() AS TotalEventCount,
SUM(e.LastIssuesCount) OVER() AS LastTotalEventCount
FROM
BaseDataSet AS e
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.ApplicationStatusClientFrequentFailure'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.ApplicationStatusClientFrequentFailure AS RETURN 1')
END
GO

/****************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: ApplicationStatusClientFrequentFailure */
/* USED IN: Application Status Client Report, top 10 Most frequent exception events */
/* INPUT PARAMETERS: */
/* @SOURCEID - Source id */
/* @COMPUTERIDS - List of the computer id, separated by comma. Exp: '1,2,3' */
/* @ENDDATE - End date of the period (in Client timezone) */
/* @PERIOD - Period type(Day, Week or Month). */
/* - Use for the Start Date calculate of the period */
/* @PROBLEM - Event problem type (all, critical) */
/* @TIMEZONE - correlate parameter (timezone by min) to return result */
/* in clien timezone */
/****************************************************************************************/
alter PROCEDURE APM.ApplicationStatusClientFrequentFailure
@SOURCEID INT,
@COMPUTERS NVARCHAR(MAX),
@ENDDATE DATETIME,
@PERIOD INT,
@PROBLEM NVARCHAR(10),
@TIMEZONE INT,
@PMSTATUS NVARCHAR(50)
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON;

SET @ENDDATE = DATEADD(minute, -@TIMEZONE, @ENDDATE)

DECLARE @STARTDATE DATETIME
SET @STARTDATE = DATEADD(d, -APM.GetQueryDateCount(@PERIOD, @ENDDATE), @ENDDATE)

CREATE TABLE #APPLICATIONSTATUSCLIENT_MACHINE
(
MACHINEID int
)

INSERT
INTO #APPLICATIONSTATUSCLIENT_MACHINE
SELECT
p.value
FROM APM.GetMultiParameters(@COMPUTERS, N'') p

-- Filter table, which contains PM Statuses of Events
CREATE TABLE #PMSTATUSFILTERTABLE(
VALUEID INT
)

-- Fill table #PMSTATUSFILTERTABLE
INSERT
INTO #PMSTATUSFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@PMSTATUS, N'') AS p

DECLARE @LASTPERIODSTARTDATE DateTime
SET @LASTPERIODSTARTDATE = DATEADD(d, -APM.GetQueryDateCount(@PERIOD, @STARTDATE), @STARTDATE)

DECLARE @CURRENTPERIODENDDATE DateTime
SET @CURRENTPERIODENDDATE = DATEADD(d, APM.GetQueryDateCount(@PERIOD, @STARTDATE), @STARTDATE)


;WITH BaseDataSet AS
(
SELECT
e.description,
e.category,
COUNT(
CASE
WHEN e.utceventdate &gt;= @STARTDATE
THEN e.eventid
END
) as EventsCount,
COUNT(
CASE
WHEN e.utceventdate &lt; @STARTDATE
THEN e.eventid
END
) AS LastEventsCount
FROM
apm.Event (NOLOCK) AS e
JOIN apm.EventGroup AS eg ON e.EventGroupId = eg.EventGroupId
JOIN #APPLICATIONSTATUSCLIENT_MACHINE AS f1 ON e.machineid = f1.MACHINEID
JOIN #PMSTATUSFILTERTABLE AS f3 ON (f3.VALUEID = e.PMStatus)
WHERE
e.EventClassType = N'Exception'
AND (e.category LIKE @PROBLEM)
AND (e.sourceId = @SOURCEID)
AND e.utceventdate &gt;= @LASTPERIODSTARTDATE
AND e.utceventdate &lt; @CURRENTPERIODENDDATE
GROUP BY
e.description, e.category
)
SELECT TOP(10)
ROW_NUMBER() OVER (ORDER BY e.EventsCount DESC, E.description) AS Id,
e.[Description],
e.Category,
e.EventsCount,
e.LastEventsCount,
-- This information is selected for event summary table
SUM(e.EventsCount) OVER() AS TotalEventCount,
SUM(e.LastEventsCount) OVER() AS LastTotalEventCount,
-- Caulculate number of different descriotions (proble, count) in current and last periods
COUNT(CASE WHEN e.EventsCount &gt; 0 THEN 1 ELSE NULL END) OVER() AS CurrentProblemsCount,
COUNT(CASE WHEN e.LastEventsCount &gt; 0 THEN 1 ELSE NULL END) OVER() AS LastProblemsCount
FROM
BaseDataSet AS e
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.ApplicationStatusClientFrequentPerformance'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.ApplicationStatusClientFrequentPerformance AS RETURN 1')
END
GO

/****************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: ApplicationStatusClientFrequentPerformance */
/* USED IN: Application Status Client Report, top 10 Most frequent performance events */
/* INPUT PARAMETERS: */
/* @SOURCEID - Source id */
/* @COMPUTERIDS - List of the computer id, separated by comma. Exp: '1,2,3' */
/* @ENDDATE - End date of the period (in Client timezone) */
/* @PERIOD - Period type(Day, Week or Month). */
/* - Use for the Start Date calculate of the period */
/* @TRESHOLD - Event duration treshold */
/* @PROBLEM - Event problem type (all, critical) */
/* @TIMEZONE - correlate parameter (timezone by min) to return result */
/* in clien timezone */
/****************************************************************************************/

alter PROCEDURE [APM].[ApplicationStatusClientFrequentPerformance]
@SOURCEID INT,
@COMPUTERS NVARCHAR(MAX),
@ENDDATE DATETIME,
@PERIOD INT,
@THRESHOLD DECIMAL(35,0),
@PROBLEM NVARCHAR(10),
@TIMEZONE INT,
@PMSTATUS NVARCHAR(50)
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON;

SET @ENDDATE = DATEADD(minute, -@TIMEZONE, @ENDDATE)

DECLARE @STARTDATE DATETIME
SET @STARTDATE = DATEADD(d, -APM.GetQueryDateCount(@PERIOD, @ENDDATE), @ENDDATE)

CREATE TABLE #APPLICATIONSTATUSCLIENT_MACHINE
(
MACHINEID INT
)

INSERT
INTO #APPLICATIONSTATUSCLIENT_MACHINE
SELECT
p.value
FROM APM.GetMultiParameters(@COMPUTERS, N'') p

-- Filter table, which contains PM Statuses of Events
CREATE TABLE #PMSTATUSFILTERTABLE(
VALUEID INT
)

-- Fill table #PMSTATUSFILTERTABLE
INSERT
INTO #PMSTATUSFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@PMSTATUS, N'') AS p

DECLARE @LASTPERIODSTARTDATE DateTime
SET @LASTPERIODSTARTDATE = DATEADD(d, -APM.GetQueryDateCount(@PERIOD, @STARTDATE), @STARTDATE)

DECLARE @CURRENTPERIODENDDATE DateTime
SET @CURRENTPERIODENDDATE = DATEADD(d, APM.GetQueryDateCount(@PERIOD, @STARTDATE), @STARTDATE)


;WITH BaseDataSet AS
(
SELECT
COUNT(CASE WHEN e.utceventdate &gt;= @STARTDATE THEN e.eventid END) as IssuesCount,
AVG(CASE WHEN e.utceventdate &gt;= @STARTDATE THEN e.eventduration / 1000000 END) AS AvgDuration,
MAX(CASE WHEN e.utceventdate &gt;= @STARTDATE THEN e.eventduration / 1000000 END) AS MaxDuration,
COUNT(CASE WHEN e.utceventdate &lt; @STARTDATE THEN e.eventid END) AS LastIssuesCount,
e.rootnodename,
(CASE
WHEN pn.description IS NOT NULL THEN RIGHT(pn.description, LEN(pn.description) - CHARINDEX(':', pn.description))
ELSE N''
END) AS PerfNodeDescription
FROM
apm.Event (NOLOCK) AS e
JOIN apm.EventGroup (NOLOCK) AS eg ON e.EventGroupId = eg.EventGroupId
JOIN apm.PerformanceNode (NOLOCK) AS pn ON pn.EventId = e.EventId
JOIN #APPLICATIONSTATUSCLIENT_MACHINE AS f ON f.MACHINEID = e.MachineId
JOIN #PMSTATUSFILTERTABLE AS f1 ON (f1.VALUEID = e.PMStatus)
WHERE
e.EventClassType = N'Performance'
AND e.eventduration / 1000000.0 &gt;= @THRESHOLD
AND e.sourceid = @SOURCEID
AND (e.category LIKE @PROBLEM OR e.category IS NULL)
AND e.utceventdate &gt;= @LASTPERIODSTARTDATE
AND e.utceventdate &lt; @CURRENTPERIODENDDATE
AND (e.HeavyLight &lt;&gt; 0 OR e.HeavyLight IS NULL)
AND pn.ISHeaviestNode = 1
GROUP BY
e.rootnodename,
(CASE
WHEN pn.description IS NOT NULL THEN RIGHT(pn.description, LEN(pn.description) - CHARINDEX(':', pn.description))
ELSE N''
END)
)
SELECT TOP(10)
ROW_NUMBER() OVER (ORDER BY e.IssuesCount DESC, e.rootnodename, PerfNodeDescription) AS Id,
e.IssuesCount,
e.AvgDuration,
e.MaxDuration,
e.LastIssuesCount,
e.rootnodename,
e.PerfNodeDescription,
e.rootnodename + (CASE
WHEN LEN(e.PerfNodeDescription) &gt; 0
THEN ' slow at ' + e.PerfNodeDescription
ELSE N'' END) AS description,
COUNT(CASE WHEN e.IssuesCount &gt; 0 THEN 1 ELSE NULL END) OVER() AS TotalCurrentProblemCount,
COUNT(CASE WHEN e.LastIssuesCount &gt; 0 THEN 1 ELSE NULL END) OVER() AS TotalLastProblemCount,
SUM(e.IssuesCount) OVER() AS TotalEventCount,
SUM(e.LastIssuesCount) OVER() AS TotalLastEventCount
FROM
BaseDataSet AS e
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.ApplicationStatusClientNewCSMEvents'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.ApplicationStatusClientNewCSMEvents AS RETURN 1')
END
GO

/****************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: ApplicationStatusClientNewCSMEvents */
/* USED IN: Application Status Client Report, top 10 New CSM events */
/* INPUT PARAMETERS: */
/* @SOURCEID - Source id */
/* @COMPUTERIDS - List of the computer id, separated by comma. Exp: '1,2,3' */
/* @ENDDATE - End date of the period (in Client timezone) */
/* @PERIOD - Period type(Day, Week or Month). */
/* - Use for the Start Date calculate of the period */
/* @TRESHOLD - Event duration treshold */
/* @PROBLEM - Event problem type (all, critical) */
/* @INCLUDESUBNET - List masks, which should be included */
/* @EXCLUDESUBNET - List masks, which should be excluded */
/* @TIMEZONE - correlate parameter (timezone by min) to return result */
/* in clien timezone */
/****************************************************************************************/

alter PROCEDURE [APM].[ApplicationStatusClientNewCSMEvents]
@SOURCEID INT,
@COMPUTERS NVARCHAR(MAX),
@ENDDATE DATETIME,
@PERIOD INT,
@THRESHOLD DECIMAL(35,0),
@PROBLEM NVARCHAR(10),
@INCLUDESUBNET NVARCHAR(MAX),
@EXCLUDESUBNET NVARCHAR(MAX),
@TIMEZONE INT
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON;

SELECT
@INCLUDESUBNET = REPLACE(@INCLUDESUBNET, N'*', N'%'),
@EXCLUDESUBNET = REPLACE(@EXCLUDESUBNET, N'*', N'%')

SET @ENDDATE = DATEADD(minute, -@TIMEZONE, @ENDDATE)

DECLARE @STARTDATE DATETIME
SET @STARTDATE = DATEADD(d, -APM.GetQueryDateCount(@PERIOD, @ENDDATE), @ENDDATE)

CREATE TABLE #APPLICATIONSTATUSCLIENT_MACHINE
(
MACHINEID INT
)

INSERT
INTO #APPLICATIONSTATUSCLIENT_MACHINE
SELECT
p.value
FROM APM.GetMultiParameters(@COMPUTERS, N'') p

-- Filter table for SubnetC values
CREATE TABLE #SUBNETCFILTERTABLE
(
IPID INT,
SUBNETC NVARCHAR(50) collate database_default
)

-- Insert into filter id of the SubnetC to increase performance for event table
INSERT INTO #SUBNETCFILTERTABLE
SELECT DISTINCT
ipid,
SubNetC
FROM
apm.IP AS ip (NOLOCK)
JOIN APM.GetMultiParameters(CASE WHEN LEN(@INCLUDESUBNET) &gt; 0 THEN @INCLUDESUBNET ELSE N'%' END, N'') AS p1 ON (ip.SubnetC LIKE p1.Value)
LEFT OUTER JOIN APM.GetMultiParameters(CASE WHEN LEN(@EXCLUDESUBNET) &gt; 0 THEN @EXCLUDESUBNET ELSE N'Fake' END, N'') AS p2 ON (ip.SubnetC LIKE p2.Value)
WHERE
--Exclude subnets which have correspondance in @EXCLUDESUBNET parameter
p2.typeId IS NULL

DECLARE @LASTPERIODSTARTDATE DateTime
SET @LASTPERIODSTARTDATE = DATEADD(d, -APM.GetQueryDateCount(@PERIOD, @STARTDATE), @STARTDATE)

DECLARE @CURRENTPERIODENDDATE DateTime
SET @CURRENTPERIODENDDATE = DATEADD(d, APM.GetQueryDateCount(@PERIOD, @STARTDATE), @STARTDATE)


SELECT TOP(10)
ROW_NUMBER() OVER (ORDER BY COUNT(e.CSEventId) DESC, eg.description) AS Id,
COUNT(e.CSEventId) as EventCount,
eg.Description,
e.ClassType,
SUM(COUNT(e.CSEventId)) OVER() AS TotalEventCount,
COUNT(*) OVER() AS TotalNewProblemsCount
FROM
apm.CSEVENT AS e (NOLOCK)
JOIN apm.CSEVENTGROUP AS eg ON e.CSEventGroupId = eg.CSEventGroupId
-- Fileter events by machines
JOIN #APPLICATIONSTATUSCLIENT_MACHINE AS f ON f.MACHINEID = e.machineid
JOIN #SUBNETCFILTERTABLE AS f1 ON e.ipid = f1.IPID
WHERE
((e.ClassType = N'Performance' AND e.TotalTime/1000.0 &gt;= @THRESHOLD)
OR e.ClassType = N'exception')
AND e.utcdate &gt;= @STARTDATE
AND e.utcdate &lt; @ENDDATE
AND e.SourceId = @SOURCEID
AND eg.SourceId = @SOURCEID
AND eg.firsteventdate &gt;= @STARTDATE
AND eg.firsteventdate &lt; @ENDDATE
AND e.PMStatus = 0
AND e.PageUri IS NOT NULL
GROUP BY
eg.Description,
e.ClassType
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.ApplicationStatusClientNewFailure'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.ApplicationStatusClientNewFailure AS RETURN 1')
END
GO


/****************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: ApplicationStatusClientNewFailure */
/* USED IN: Application Status Client Report, top 10 new exception events */
/* INPUT PARAMETERS: */
/* @SOURCEID - Source id */
/* @COMPUTERIDS - List of the computer id, separated by comma. Exp: '1,2,3' */
/* @ENDDATE - End date of the period (in Client timezone) */
/* @PERIOD - Period type(Day, Week or Month). */
/* - Use for the Start Date calculate of the period */
/* @PROBLEM - Event problem type (all, critical) */
/* @TIMEZONE - correlate parameter (timezone by min) to return result */
/* in clien timezone */
/****************************************************************************************/

alter PROCEDURE [APM].[ApplicationStatusClientNewFailure]
@SOURCEID INT,
@COMPUTERS NVARCHAR(MAX),
@ENDDATE DATETIME,
@PERIOD INT,
@PROBLEM NVARCHAR(10),
@TIMEZONE INT
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON;

SET @ENDDATE = DATEADD(minute, -@TIMEZONE, @ENDDATE)

DECLARE @STARTDATE DATETIME
SET @STARTDATE = DATEADD(d, -APM.GetQueryDateCount(@PERIOD, @ENDDATE), @ENDDATE)

CREATE TABLE #APPLICATIONSTATUSCLIENT_MACHINE
(
MACHINEID INT
)

INSERT
INTO #APPLICATIONSTATUSCLIENT_MACHINE
SELECT
p.value
FROM APM.GetMultiParameters(@COMPUTERS, N'') p

SELECT TOP(10)
ROW_NUMBER() OVER (ORDER BY COUNT(e.eventid) DESC, e.description) AS Id,
e.description,
e.category,
COUNT(e.eventid) as EventsCount,
SUM(COUNT(e.eventid)) OVER() AS TotalEventCount,
COUNT(*) OVER() AS TotalNewProblemsCount
FROM
apm.Event (NOLOCK) AS e
JOIN #APPLICATIONSTATUSCLIENT_MACHINE AS f ON f.MACHINEID = e.machineid
JOIN apm.eventgroup (NOLOCK) AS eg ON e.eventGroupId = eg.EventGroupId
WHERE
e.EventClassType = N'Exception'
AND e.SourceId = @SOURCEID
AND eg.SourceId = @SOURCEID
AND (e.category LIKE @PROBLEM)
AND e.utceventdate &gt;= @STARTDATE
AND e.utceventdate &lt; @ENDDATE
AND eg.firsteventdate &gt;= @STARTDATE
AND eg.firsteventdate &lt; @ENDDATE
AND e.PMStatus = 0
GROUP BY
e.description, e.category
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.ApplicationStatusClientNewPerformance'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.ApplicationStatusClientNewPerformance AS RETURN 1')
END
GO
/****************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: ApplicationStatusClientNewPerformance */
/* USED IN: Application Status Client Report, top 10 New performance events */
/* INPUT PARAMETERS: */
/* @SOURCEID - Source id */
/* @COMPUTERIDS - List of the computer id, separated by comma. Exp: '1,2,3' */
/* @ENDDATE - End date of the period (in Client timezone) */
/* @PERIOD - Period type(Day, Week or Month). */
/* - Use for the Start Date calculate of the period */
/* @TRESHOLD - Event duration treshold */
/* @PROBLEM - Event problem type (all, critical) */
/* @TIMEZONE - correlate parameter (timezone by min) to return result */
/* in clien timezone */
/****************************************************************************************/
alter PROCEDURE [APM].[ApplicationStatusClientNewPerformance]
@SOURCEID INT,
@COMPUTERS NVARCHAR(MAX),
@ENDDATE DATETIME,
@PERIOD INT,
@THRESHOLD DECIMAL(35,0),
@PROBLEM NVARCHAR(10),
@TIMEZONE INT
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON;

SET @ENDDATE = DATEADD(minute, -@TIMEZONE, @ENDDATE)

DECLARE @STARTDATE DATETIME
SET @STARTDATE = DATEADD(d, -APM.GetQueryDateCount(@PERIOD, @ENDDATE), @ENDDATE)

CREATE TABLE #APPLICATIONSTATUSCLIENT_MACHINE
(
MACHINEID INT
)

INSERT
INTO #APPLICATIONSTATUSCLIENT_MACHINE
SELECT
p.value
FROM APM.GetMultiParameters(@COMPUTERS, N'') p
;WITH BaseDatSet AS
(
SELECT
COUNT(e.eventid) as IssuesCount,
AVG(e.eventduration / 1000000) AS AvgDuration,
MAX(e.eventduration / 1000000) AS MaxDuration,
e.rootnodename,
(CASE
WHEN pn.description IS NOT NULL THEN RIGHT(pn.description, LEN(pn.description) - CHARINDEX(':', pn.description))
ELSE N''
END) AS PerfNodeDescription
FROM
APM.Event (nolock) AS e
JOIN #APPLICATIONSTATUSCLIENT_MACHINE AS f ON f.MACHINEID = e.machineid
JOIN APM.PerformanceNode (NOLOCK) AS pn ON pn.EventId = e.EventId
JOIN APM.eventgroup (NOLOCK) AS eg ON E.EventGroupId = eg.EventGroupId
WHERE
e.EventClassType = N'Performance' AND e.eventduration / 1000000.0 &gt;= @THRESHOLD
AND (e.category LIKE @PROBLEM OR e.category IS NULL)
AND e.utceventdate &gt;= @STARTDATE
AND e.utceventdate &lt; @ENDDATE
AND e.SourceId = @SOURCEID
AND eg.SourceId = @SOURCEID
AND eg.firsteventdate &gt;= @STARTDATE
AND eg.firsteventdate &lt; @ENDDATE
AND pn.IsHeaviestNode = 1
AND e.PMStatus = 0
GROUP BY
e.rootnodename,
(CASE
WHEN pn.description IS NOT NULL THEN RIGHT(pn.description, LEN(pn.description) - CHARINDEX(':', pn.description))
ELSE N''
END)
)
SELECT TOP(10)
ROW_NUMBER() OVER (ORDER BY e.IssuesCount DESC, e.rootnodename, e.PerfNodeDescription) AS Id,
e.IssuesCount,
e.AvgDuration,
e.MaxDuration,
e.rootnodename,
e.PerfNodeDescription,
e.rootnodename + (CASE
WHEN LEN(e.PerfNodeDescription) &gt; 0
THEN ' slow at ' + e.PerfNodeDescription
ELSE N'' END) AS description,
SUM(IssuesCount) OVER() AS EventsSum,
COUNT(*) OVER() AS TotalNewProblemsCount
FROM
BaseDatSet AS e
ORDER BY
IssuesCount DESC
END
GO


-------------------- Rule management --------------------------------
IF (OBJECTPROPERTY(OBJECT_ID('APM.V_PM_EMPTY'), 'IsView') IS NULL) BEGIN
EXECUTE('CREATE VIEW APM.V_PM_EMPTY
AS
select clmn=1')
END
GO

alter VIEW [APM].[V_PM_EMPTY] AS
SELECT N'' AS VAL , -1 AS PMSTATUS, -1 AS SEVIEWERDBID, -1 AS EVENTID
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.V_PM_CSEVENTSTATUS'), 'IsView') IS NULL) BEGIN
EXECUTE('CREATE VIEW APM.V_PM_CSEVENTSTATUS
AS
select clmn=1')
END
GO

alter VIEW [APM].[V_PM_CSEVENTSTATUS] AS
SELECT E.CSEVENTID AS EVENTID, E.PMSTATUS, E.ROWGUID, E.SEVIEWERDBID
FROM APM.CSEVENT AS E (NOLOCK)
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.V_PM_HEAVIESTNODE'), 'IsView') IS NULL) BEGIN
EXECUTE('CREATE VIEW APM.V_PM_HEAVIESTNODE
AS
select clmn=1')
END
GO

alter VIEW [APM].[V_PM_HEAVIESTNODE] AS
SELECT
E.EVENTID,
E.PMSTATUS,
E.SEVIEWERDBID,
COALESCE(P.DESCRIPTION, N'Internal Execution') AS VAL,
COALESCE(P.SELFDURATION, E.EVENTDURATION / 1000.0) AS SELFDURATION
FROM
APM.EVENT (NOLOCK) AS e
LEFT JOIN APM.PERFORMANCENODE (NOLOCK) p ON p.eventid = e.eventid
WHERE
p.ISHEAVIESTNODE = 1
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.V_PM_CSHEAVIESTNODE'), 'IsView') IS NULL) BEGIN
EXECUTE('CREATE VIEW APM.V_PM_CSHEAVIESTNODE
AS
select clmn=1')
END
GO

alter VIEW [APM].[V_PM_CSHEAVIESTNODE] AS
SELECT
E.CSEVENTID AS EVENTID,
E.PMSTATUS,
E.SEVIEWERDBID,
COALESCE(P.NAME, N'Internal Execution') AS VAL,
P.DURATION AS SELFDURATION
FROM
APM.CSEVENT (NOLOCK) AS e
LEFT JOIN APM.CSHEAVIESTRESOURCE (NOLOCK) p ON p.cseventid = e.cseventid
WHERE
p.ISHEAVIESTNODE = 1
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.V_PM_EVENT'), 'IsView') IS NULL) BEGIN
EXECUTE('CREATE VIEW APM.V_PM_EVENT
AS
select clmn=1')
END
GO

alter VIEW APM.V_PM_EVENT AS
SELECT
E.EVENTID,
S.SOURCE,
M.MACHINE AS MACHINENAME,
U.NAME AS USERNAME,
E.EVENTCLASSTYPE,
E.ROOTNODENAME,
E.DESCRIPTION,
E.EXCEPTIONCLASS,
E.EVENTDURATION,
E.SEVIEWEREGID,
E.HEAVYLIGHT,
E.ASPECT,
E.SEVIEWERDBID,
E.ROWGUID,
E.CATEGORY,
E.PMSTATUS
FROM APM.EVENT (NOLOCK) AS E
JOIN apm.SOURCE S (NOLOCK) ON S.SOURCEID = E.SOURCEID
JOIN apm.MACHINE M (NOLOCK) ON M.MACHINEID = E.MACHINEID
LEFT JOIN apm.USERS U (NOLOCK) ON U.USERID = E.USERID
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.V_PM_EVENTDETAIL'), 'IsView') IS NULL) BEGIN
EXECUTE('CREATE VIEW APM.V_PM_EVENTDETAIL
AS
select clmn=1')
END
GO

alter VIEW [APM].[V_PM_EVENTDETAIL] AS
SELECT E.EVENTID, E.PMSTATUS, E.SEVIEWERDBID, D.VALUE, D.NAME
FROM APM.EVENT (NOLOCK) AS e
JOIN APM.EVENTDETAIL (NOLOCK) d ON d.eventid = e.eventid
WHERE
d.ValueType = N'PM'
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.V_PM_CSEVENTDETAIL'), 'IsView') IS NULL) BEGIN
EXECUTE('CREATE VIEW APM.V_PM_CSEVENTDETAIL
AS
select clmn=1')
END
GO

alter VIEW [APM].[V_PM_CSEVENTDETAIL] AS
SELECT E.CSEVENTID AS EVENTID, E.PMSTATUS, E.SEVIEWERDBID, D.VALUE, D.NAME
FROM APM.CSEVENT (NOLOCK) AS e
JOIN APM.CSEVENTDETAIL (NOLOCK) d ON d.cseventid = e.cseventid
WHERE
d.ValueType = N'PM'
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.V_PM_RESOURCE'), 'IsView') IS NULL) BEGIN
EXECUTE('CREATE VIEW APM.V_PM_RESOURCE
AS
select clmn=1')
END
GO

alter VIEW [APM].[V_PM_RESOURCE] AS
SELECT P.EVENTID, E.SEVIEWERDBID, E.PMSTATUS, P.RESOURCEMETHOD
FROM APM.PERFORMANCENODE p (NOLOCK)
JOIN apm.EVENT e (NOLOCK) ON e.eventid = p.eventid
WHERE
p.ISHEAVIESTNODE = 1
UNION ALL
SELECT E.EVENTID, E.SEVIEWERDBID, E.PMSTATUS, EX.RESOURCEMETHOD
FROM APM.EXCEPTIONNODE ex (NOLOCK)
JOIN apm.EVENT e (NOLOCK) ON e.eventid = EX.eventid
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.V_PM_CSEVENT'), 'IsView') IS NULL) BEGIN
EXECUTE('CREATE VIEW APM.V_PM_CSEVENT
AS
select clmn=1')
END
GO

alter VIEW APM.V_PM_CSEVENT AS
SELECT
E.CSEVENTID AS EVENTID,
S.SOURCE,
M.MACHINE AS MACHINENAME,
U.NAME AS USERNAME,
E.CLASSTYPE AS EVENTCLASSTYPE,
E.DESCRIPTION AS [DESCRIPTION],
E.TOTALTIME * 1000 AS EVENTDURATION,
SEVIEWEREGID AS EVENTGROUPID,
E.SEVIEWERDBID,
2 AS HEAVYLIGHT,
CASE
WHEN CLASSTYPE = N'exception' THEN N'Web Page Client Side Exception'
END AS EXCEPTIONCLASS,
N'Unknown' AS COMPONENT,
CASE
WHEN CLASSTYPE = N'performance' THEN N'performance'
WHEN CLASSTYPE = N'exception' THEN N'applicationfailure'
END AS ASPECT,
E.ROWGUID,
PMSTATUS,
SEVIEWEREGID
FROM APM.CSEVENT (NOLOCK) AS E
JOIN apm.SOURCE S (NOLOCK) ON S.SOURCEID = E.SOURCEID
JOIN apm.MACHINE M (NOLOCK) ON M.MACHINEID = E.MACHINEID
LEFT JOIN apm.USERS U (NOLOCK) ON U.USERID = E.USERID
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.PMACTIONQUERY'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.PMACTIONQUERY AS RETURN 1')
END
GO

/******************************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: PMACTIONQUERY */
/* INPUT PARAMETERS: */
/* @RULEDESCRIPTION - rule description */
/* @CLIENT - client event flag : 0 - server event 1 - client event */
/* @DBID - seviewer database id. SEviewerDb primary key */
/* @LASTPARAMETERINDEX - last parameter index */
/* OUTPUT PARAMETERS: */
/* @QUERY_CURSOR - result cursor */
/* DESCRIPTION: */
/* It processed actions and create action parameter description that will be used */
/* during call sp_execute. Also database id parameter has been added into the output */
/* result cursor @QUERY_CURSOR will be contains paramaters description */
/* --------------|------------|-----------------------------------|------------------|-------------| */
/* parameter | field name | action &amp; db paramater descriptions| parameter values | entity name | */
/* --------------|------------|-----------------------------------|------------------|-------------| */
/* For example, rule description has following structure: */
/* &lt;actions&gt; */
/* &lt;action alias="EVENT.PMSTATUS" action="Intercept.ActionType.ChangeStatus"&gt; */
/* &lt;params&gt; */
/* &lt;param name="value" value="3" /&gt; */
/* &lt;/params&gt; */
/* &lt;/action&gt; */
/* &lt;/actions&gt; */
/* Output for this action will be following ( @LASTPARAMETERINDEX = 2, @DBID = 1, @CLIENT = 0 */
/* --------------|------------|-----------------------------------|------------------|-------------| */
/* @A3 | PMSTATUS | @A3 tinyint,@DBID int | 3,1 | EVENT | */
/* --------------|------------|-----------------------------------|------------------|-------------| */
/******************************************************************************************************/
alter PROCEDURE [APM].[PMACTIONQUERY]
@RULEDESCRIPTION as NVARCHAR(max)
,@CLIENT bit
,@DBID int
,@LASTPARAMETERINDEX int = 0
,@QUERY_CURSOR CURSOR VARYING OUTPUT
AS
BEGIN
SET NOCOUNT ON;

DECLARE
@ERRORIND BIT
,@ERRORMESSAGE NVARCHAR(4000)
,@ERRORNUMBER INT
,@ERRORSEVERITY INT
,@ERRORSTATE INT
,@ERRORLINE INT
,@ERRORPROCEDURE SYSNAME
,@ERRORMESSAGETEXT NVARCHAR(4000)

SET @ERRORIND = 0

BEGIN TRY

DECLARE
@RULE AS XML

--convert rule description to untyped xml
SET @RULE = CAST(@RULEDESCRIPTION AS XML)

--declare result query
DECLARE
@QUERYSET TABLE
(
entity SYSNAME -- entity name (stored procedure or table/view)
,actionParameter nvarchar(50) -- action parameter name corresponding action field
,actionField nvarchar(50) -- action field (now "pmstatus")
,params NVARCHAR(MAX) -- list of parameter names (action parameter + database id parameter)
,paramsValues NVARCHAR(MAX) -- parameter values corresponding list of parameter names
,lastParameterIndex int -- last index parameter, for stored procedure is always zero
,procParameterList NVARCHAR(max) -- list of stored proc parameter names
)


--------------- actions query ------------
DECLARE
actions_cursor CURSOR STATIC FOR
SELECT actions._action.query('.')
FROM @RULE.nodes('rule/actions/action') actions(_action)
DECLARE
@ACTION AS XML

OPEN actions_cursor

FETCH NEXT FROM actions_cursor
INTO @ACTION

-------------- cycle by actions --------------
WHILE @@FETCH_STATUS = 0
BEGIN
DECLARE
@ALIAS nvarchar(50)

-- Get alias name that using for extract entity name
SELECT @ALIAS = @ACTION.value('(/action/@alias)[1]', 'nvarchar(50)')

DECLARE
@ENTITY nvarchar(50) -- entity name
,@FIELD nvarchar(50) -- field name
,@FIELDTYPE nvarchar(50) -- field type

DECLARE
@PARAMS NVARCHAR(MAX) -- list of parameter names
,@PARAMSVALUES NVARCHAR(MAX) -- list of parameter values
,@CHARCONDITIONFLAG bit -- char condition flag
,@PROCPARAMETERLIST NVARCHAR(max) --reserved (parameter name list for call stored procedure)
,@ISPROCEDURE bit --entity is procedure. 0 - not procedure 1 - procedure
,@VALUES_CURSOR CURSOR -- cursor for extracting parameter and corresponding values

-- lookup for field, field type, entity name, procedure flag
SELECT
@FIELD = field
,@FIELDTYPE = fieldType
,@ENTITY = entity
,@ISPROCEDURE = isprocedure
FROM
APM.PMENTITYMAPPING (NOLOCK)
WHERE
alias = @ALIAS AND isclient = @CLIENT

IF @@ROWCOUNT = 0
BEGIN
-- alias is not found. raise error
RAISERROR(N'Alias "%s" is not registered', 16, 1, @ALIAS)
RETURN
END

-- clear previos parameter list and check field type.
SELECT
@PARAMS = N''
,@PARAMSVALUES = N''
--flag char character field(1- char field 0- not char field)
,@CHARCONDITIONFLAG = CASE WHEN CHARINDEX(N'char', @FIELDTYPE) &gt; 0 THEN 1 ELSE 0 END

-- initialize parameter list
SELECT
@LASTPARAMETERINDEX = CASE WHEN @ISPROCEDURE = 1 THEN 0 ELSE lastParameterIndex END --last prameter index
,@PARAMS = N''
,@PARAMSVALUES = N''
FROM
@QUERYSET
WHERE
entity = @ENTITY

--------------- values query ------------

--iteration by parameter. Get parameter name and value
SET @VALUES_CURSOR = CURSOR STATIC FOR
SELECT
valueSet.value.value('(@value)[1]', 'nvarchar(max)'), -- parameter value
valueSet.value.value('(@name)[1]', 'nvarchar(max)') -- parameter name
FROM
@ACTION.nodes('/action/params/param') valueSet(value)

-- open cursor
OPEN @VALUES_CURSOR

DECLARE
@VALUE NVARCHAR(MAX) -- parameter value
,@NAME nvarchar(max) -- parameter name
,@DECORATOR nvarchar(1) -- decorator for value

SELECT
@PROCPARAMETERLIST = N'' -- clear proc parameter list
,@DECORATOR = CASE WHEN @CHARCONDITIONFLAG = 1 THEN '''' ELSE '' END -- define value decorator (for example 'value' or value)

-- fetch parameter name and value
FETCH NEXT FROM @VALUES_CURSOR
INTO @VALUE, @NAME

---------- cycle by values --------
WHILE @@FETCH_STATUS = 0
BEGIN
-- increment last parameter index
SELECT @LASTPARAMETERINDEX = @LASTPARAMETERINDEX + 1

DECLARE
@PARAMETERNAME nvarchar(MAX)
,@PARAMETERVALUE nvarchar(max)

SELECT
-- for procedure parameter name equal @NAME otherwise using format "@A{last parameter index}"
@PARAMETERNAME =
CASE
WHEN @ISPROCEDURE = 1
THEN REPLACE(N'@{0}', N'{0}', @NAME)
ELSE REPLACE(N'@A{0}', N'{0}', @LASTPARAMETERINDEX)
END
-- create proc parameter list
IF @ISPROCEDURE = 1
BEGIN
-- parameter list divided by ','
SELECT @PROCPARAMETERLIST = @PROCPARAMETERLIST +
REPLACE(REPLACE(N'{0}{1}',
N'{0}',CASE WHEN LEN(@PROCPARAMETERLIST) &gt; 0 THEN N',' ELSE '' END),
N'{1}',@PARAMETERNAME)
-- calculate parameter type
SELECT @FIELDTYPE = APM.GetProcParameterTypeName(@ENTITY, @PARAMETERNAME)
IF @FIELDTYPE IS NULL
BEGIN
-- parameter type is not divided, raise exception
RAISERROR(N'Parameter "%s" for stored procedure "%s" is not defined.', 16, 1, @PARAMETERNAME, @ENTITY)
RETURN
END
-- define char condition flag
SELECT @CHARCONDITIONFLAG = CASE WHEN CHARINDEX(N'char', @FIELDTYPE) &gt; 0 THEN 1 ELSE 0 END
-- define value decorator (for example 'value' or value)
SELECT @DECORATOR = CASE WHEN @CHARCONDITIONFLAG = 1 THEN '''' ELSE '' END
END
--create parameter value using decorator
SELECT @PARAMETERVALUE = REPLACE(REPLACE(REPLACE(
N'{0}{1}{2}',
N'{0}',@DECORATOR),
N'{1}',@VALUE),
N'{2}',@DECORATOR)
SELECT
-- create parameter list for table/view entity divided by ',' (format - "parameter name parameter type")
@PARAMS = @PARAMS + REPLACE(REPLACE(REPLACE(CONVERT(nvarchar(max),
N'{0}{1} {2}'),
N'{0}',CASE WHEN LEN(@PARAMS) &gt; 0 THEN N',' ELSE N'' END),
N'{1}',@PARAMETERNAME),
N'{2}',@FIELDTYPE)
-- param value list divided by ','
,@PARAMSVALUES = @PARAMSVALUES + REPLACE(REPLACE(CONVERT(nvarchar(max),N'{0}{1}'),
N'{0}',CASE WHEN LEN(@PARAMSVALUES) &gt; 0 THEN N',' ELSE N'' END),
N'{1}',@PARAMETERVALUE)

FETCH NEXT FROM @VALUES_CURSOR
INTO @VALUE, @NAME
END
CLOSE @VALUES_CURSOR
DEALLOCATE @VALUES_CURSOR

--------------- end values query ------------

SELECT
--- Add database id parameter name ----
@PARAMS = @PARAMS + REPLACE(REPLACE(CONVERT(nvarchar(max),N',{0} {1}'),
N'{0}',N'@DBID'),
N'{1}',N'int')

--- Add database id parameter value ----
,@PARAMSVALUES = @PARAMSVALUES + REPLACE(CONVERT(nvarchar(max),N',{0}'),N'{0}',@DBID)

-- insert into result set
INSERT @QUERYSET (actionField, actionParameter, entity, lastParameterIndex, params, paramsValues, procParameterList)
VALUES(@FIELD, @PARAMETERNAME, @ENTITY, @LASTPARAMETERINDEX, @PARAMS, @PARAMSVALUES, @PROCPARAMETERLIST)

--- Get next expression ----------
FETCH NEXT FROM actions_cursor
INTO @ACTION
END
CLOSE actions_cursor
DEALLOCATE actions_cursor

-- create result cursor for action parameter, action field, parameter list, parameter values
SET @QUERY_CURSOR = CURSOR STATIC FORWARD_ONLY FOR
SELECT
actionParameter
,actionField
,params
,paramsValues
,entity
FROM
@QUERYSET

OPEN @QUERY_CURSOR

END TRY
BEGIN CATCH
IF (@@TRANCOUNT &gt; 0)
ROLLBACK TRAN

SELECT
@ERRORNUMBER = ERROR_NUMBER()
,@ERRORSEVERITY = ERROR_SEVERITY()
,@ERRORSTATE = ERROR_STATE()
,@ERRORLINE = ERROR_LINE()
,@ERRORPROCEDURE = ISNULL(ERROR_PROCEDURE(), '-')
,@ERRORMESSAGETEXT = ERROR_MESSAGE()

SET @ERRORIND = 1
END CATCH

IF (@ERRORIND = 1)
BEGIN
IF CURSOR_STATUS('global', 'actions_cursor') IN (0,1)
CLOSE actions_cursor
IF CURSOR_STATUS('global', 'actions_cursor') = -1
DEALLOCATE actions_cursor

DECLARE
@ADJUSTEDERRORSEVERITY INT

SET @ADJUSTEDERRORSEVERITY = CASE
WHEN @ERRORSEVERITY &gt; 18 THEN 18
ELSE @ERRORSEVERITY
END


RAISERROR (@ERRORMESSAGETEXT, @ADJUSTEDERRORSEVERITY, 1
,@ERRORNUMBER
,@ERRORSEVERITY
,@ERRORSTATE
,@ERRORPROCEDURE
,@ERRORLINE
,@ERRORMESSAGETEXT
)
END
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.PMEXPRESSIONQUERY'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.PMEXPRESSIONQUERY AS RETURN 1')
END
GO

/******************************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: PMEXPRESSIONQUERY */
/* INPUT PARAMETERS: */
/* @RULEDESCRIPTION - rule description */
/* @CLIENT - client event flag : 0 - server event 1 - client event */
/* @DBID - seviewer database id. SEviewerDb primary key */
/* OUTPUT PARAMETERS: */
/* @QUERY_CURSOR - result cursor */
/* DESCRIPTION: */
/* It processed expressions and create for each entity "where" sql conditions using list of parameters*/
/* Sql condition also contains action and database id parameters. */
/* If entity is stored procedure then will be create only proc parameter list. */
/* For entity "V_PM_EVENTDETAIL" the column "fieldType" of table PMENTITYMAPPING contains value that */
/* will be used for additional sql condition {Name = {value}}.( See example below for expression */
/* &lt;expression alias="EVENT.COMPONENT"&gt;) */
/* Result cursor will be contains next fields */
/* --------|---------------|------------|------------------|----------------------|----------------- */
/* entity | sql condition | parameters | parameter values | last parameter index | proc parameters */
/* --------|---------------|------------|------------------|----------------------|----------------- */
/* For example, rule description has following structure: */
/*&lt;rule name="Event Type" id="1" dbid="7D7A57B2-32C8-4520-9DA8-1A771BBCC7C8"&gt; */
/* &lt;expressions&gt; */
/* &lt;expression alias="EVENT.EVENTCLASSTYPE" variable="Intercept.Variable.EventClassType"&gt; */
/* &lt;params&gt; */
/* &lt;param name="operation" value="IN" /&gt; */
/* &lt;param name="value" value="performance" /&gt; */
/* &lt;/params&gt; */
/* &lt;/expression&gt; */
/* &lt;expression alias="EVENT.SOURCE" variable="Intercept.Variable.Source"&gt; */
/* &lt;params&gt; */
/* &lt;param name="operation" value="IN" /&gt; */
/* &lt;param name="value" value="Duwamish7" /&gt; */
/* &lt;param name="value" value="Default Web Site/WebService1" /&gt; */
/* &lt;/params&gt; */
/* &lt;/expression&gt; */
/* &lt;expression alias="EVENT.COMPONENT" variable="Intercept.Variable.EventClassType"&gt; */
/* &lt;params&gt; */
/* &lt;param name="operation" value="IN" /&gt; */
/* &lt;param name="value" value="performance" /&gt; */
/* &lt;/params&gt; */
/* &lt;/expression&gt; */
/* &lt;/expressions&gt; */
/* &lt;actions&gt; */
/* &lt;action alias="EVENT.PMSTATUS" action="Intercept.ActionType.ChangeStatus"&gt; */
/* &lt;params&gt; */
/* &lt;param name="value" value="0" /&gt; */
/* &lt;/params&gt; */
/* &lt;/action&gt; */
/* &lt;/actions&gt; */
/*&lt;/rule&gt; */
/* Output for this rule will be following ( @CLIENT = 0, @DBID = 1) */
/* Note: action parameter value and database identifier are not included in parameter value list */
/* -----------|-------------------------|------------------|-------------------------------|-|--| */
/* V_PM_EVENT |(EVENTCLASSTYPE like @P1 | @P1 nvarchar(50) |'performance', |3| | */
/* | |,@P2 nvarchar(255)|'Default Web Site/WebService1',| | | */
/* | ESCAPE N''~'' ) AND |,@P3 nvarchar(255)|'Duwamish7' | | | */
/* | (SOURCE like @P2 | | | | | */
/* | ESCAPE N''~'' OR | | | | | */
/* | SOURCE like @P3 | | | | | */
/* | ESCAPE N''~'') AND | | | | | */
/* | (PMSTATUS != @A1 AND | | | | | */
/* | SEVIEWERDBID = @DBID) | | | | | */
/* | | | | | | */
/* -----------|-------------------------|------------------|-------------------------------|-|--| */
/* V_PM_EVENT |(VALUE like @P4 |@P4 nvarchar(255) |'performance','COMPONENT' |5| | */
/* DETAIL | ESCAPE N''~'' ) AND|@P5 nvarchar(50) | | | | */
/* | NAME=@P5 AND | | | | | */
/* | ( PMSTATUS != @A1 AND | | | | | */
/* | SEVIEWERDBID = @DBID | | | | | */
/* | ) | | | | | */
/* | | | | | | */
/*************|****************************************************************************************/
alter PROCEDURE [APM].[PMEXPRESSIONQUERY]
@RULEDESCRIPTION as NVARCHAR(max)
,@CLIENT bit
,@DBID int
,@QUERY_CURSOR CURSOR VARYING OUTPUT
AS
BEGIN
SET NOCOUNT ON;

DECLARE
@ERRORIND BIT
,@ERRORMESSAGE NVARCHAR(4000)
,@ERRORNUMBER INT
,@ERRORSEVERITY INT
,@ERRORSTATE INT
,@ERRORLINE INT
,@ERRORPROCEDURE SYSNAME
,@ERRORMESSAGETEXT NVARCHAR(4000)

SET @ERRORIND = 0

BEGIN TRY

DECLARE
@RULE AS XML
,@EVENTDETAILENTITY sysname
,@CSEVENTDETAILENTITY sysname

SELECT
-- convert rule to untyped xml
@RULE = CAST(@RULEDESCRIPTION AS XML)
-- server entity name that need processed separate
,@EVENTDETAILENTITY = N'V_PM_EVENTDETAIL'
-- client entity name that need processed separate
,@CSEVENTDETAILENTITY = N'V_PM_CSEVENTDETAIL'

-- Result Set
DECLARE
@QUERYSET TABLE
(
id int IDENTITY (1,1) -- identity . Unique identifier
,entity SYSNAME -- entity name. For eventdetail entity can be several row with the same entity name.
,condition NVARCHAR(MAX) -- sql condition that will be used for 'where' clause
,params NVARCHAR(MAX) -- parameter list that will be used for 'where' clause
,paramsValues NVARCHAR(MAX) --parameter value list that will be used for 'where' clause
,lastParameterIndex int -- last parameter index that used for paramater list
,procParameterList NVARCHAR(max) -- proc parameters if entity is stored proc. Reserved.
)

--------------- expressions query ------------
DECLARE
expressions_cursor CURSOR STATIC FOR
SELECT expressions.expression.query('.') AS expr
FROM @RULE.nodes('rule/expressions/expression') expressions(expression)
DECLARE
@EXPRESSION AS XML

OPEN expressions_cursor

FETCH NEXT FROM expressions_cursor INTO @EXPRESSION

DECLARE
@LASTPARAMETERINDEX int

SELECT @LASTPARAMETERINDEX = 0

-------------- cycle by expressions --------------
WHILE @@FETCH_STATUS = 0
BEGIN
DECLARE
@ALIAS nvarchar(50)

-- Get alias name
SELECT @ALIAS = @EXPRESSION.value('(/expression/@alias)[1]', 'nvarchar(50)')

DECLARE
@ENTITY nvarchar(50) -- entity name
,@FIELD nvarchar(50) -- field name that used in condition
,@OPERATION NVARCHAR(50) -- operation
,@FIELDTYPE nvarchar(50) -- field type
,@NOTEXPRESSION bit -- expression contains 'not' ( 0 - not contains 1 - contains)
,@ISPROCEDURE bit -- entity is procedure ( 0 - table/view 1-procedure)

-- Get operation
SELECT
@OPERATION = @EXPRESSION.value('(/expression/params/param[@name=''operation'']/@value)[1]', 'nvarchar(50)')

SELECT
-- expression contains "not" clause (1-contains, 0-not contains)
@NOTEXPRESSION = CASE WHEN CHARINDEX(N'not', @OPERATION) &gt; 0 THEN 1 ELSE 0 END
-- operation
,@OPERATION = REPLACE(@OPERATION, N'not', N'')

DECLARE
@CONDITION NVARCHAR(MAX) -- sql condition
,@PARAMS NVARCHAR(MAX) -- parameter list divided by ','
,@PARAMSVALUES NVARCHAR(MAX) -- param value list divided by ','
,@PARAMTYPE sysname -- parameter type
,@CHARCONDITIONFLAG bit -- flag char character field(1- char field 0- not char field)
,@PREFIX nvarchar(10) -- for "not" expression use "NOT" clause otherwise use empty prefix
,@PROCPARAMETERLIST NVARCHAR(max) -- proc parameter list
,@VALUES_CURSOR CURSOR -- cursor for extracting parameter and corresponding values

-- seach mapping for alias
SELECT
--use 'rowguid' instead 'eventid' field
@FIELD = CASE field WHEN N'EVENTID' THEN N'ROWGUID' ELSE field END
--user nvarchar(50) for rowguid field
,@FIELDTYPE = CASE field WHEN N'EVENTID' THEN N'nvarchar(50)' ELSE fieldType END
--entity name
,@ENTITY = entity
--stored proc flag
,@ISPROCEDURE = isprocedure
FROM
APM.PMENTITYMAPPING (NOLOCK)
WHERE
alias = @ALIAS AND isclient = @CLIENT

IF @@ROWCOUNT = 0
BEGIN
-- mapping for alias not found, raise exception
RAISERROR(N'Alias "%s" is not registered', 16, 1, @ALIAS)
RETURN
END

-- initialize
SELECT @CONDITION = N''
,@PARAMS = N''
,@PARAMSVALUES = N''
-- use always char condition for eventdetail table or for 'rowguid' field
,@CHARCONDITIONFLAG =
CASE
WHEN (CHARINDEX(N'char', @FIELDTYPE) &gt; 0) OR (@ENTITY = @CSEVENTDETAILENTITY) OR
(@ENTITY = @EVENTDETAILENTITY) OR (@FIELD = N'ROWGUID')
THEN 1
ELSE 0
END
-- initialize prefix. For not char fields use empty prefix
SELECT @PREFIX = CASE WHEN @NOTEXPRESSION = 1 AND @CHARCONDITIONFLAG = 1 THEN N'NOT' ELSE N'' END

-- for not eventdetail entity sql conditions and parameters will be united for the same entity
-- for eventdetail always use new sql condition and parameters
IF (@ENTITY != @CSEVENTDETAILENTITY) AND (@ENTITY != @EVENTDETAILENTITY)
SELECT
@CONDITION = CASE WHEN @ISPROCEDURE = 1 THEN N'' ELSE condition END
,@PARAMS = CASE WHEN @ISPROCEDURE = 1 THEN N'' ELSE params END
,@PARAMSVALUES = CASE WHEN @ISPROCEDURE = 1 THEN N'' ELSE paramsValues END
FROM
@QUERYSET
WHERE
entity = @ENTITY

-- begin create sql condition. The first prefix will be added
SELECT @CONDITION = @CONDITION +
CASE WHEN LEN(@CONDITION) &gt; 0
THEN REPLACE(CONVERT(nvarchar(MAX),N' AND {0} ('), N'{0}', @PREFIX)
ELSE REPLACE(CONVERT(nvarchar(MAX),N' {0} ('), N'{0}', @PREFIX)
END

--------------- values query ------------
-- prepare cursor for select parameter names and values
if @ISPROCEDURE = 1
SET @VALUES_CURSOR = CURSOR STATIC FOR
SELECT valueSet.value.value('(@value)[1]', 'nvarchar(max)'),valueSet.value.value('(@name)[1]', 'nvarchar(max)')
FROM @EXPRESSION.nodes('/expression/params/param') valueSet(value)
ELSE
SET @VALUES_CURSOR = CURSOR STATIC FOR
SELECT valueSet.value.value('(@value)[1]', 'nvarchar(max)'), N''
FROM @EXPRESSION.nodes('/expression/params/param[@name=''value'']') valueSet(value)

-- open values cursor
OPEN @VALUES_CURSOR

DECLARE
@VALUE NVARCHAR(MAX) -- parameter value
,@NAME nvarchar(max) -- parameter name
,@CHARCONDITION nvarchar(max) -- sql condition for char values
,@NUMBERCONDITION nvarchar(max) -- sql condition for non char values
,@DECORATOR nvarchar(1) -- decorator. (Use ''' or empty decorator for values)
,@POSTFIX nvarchar(50) -- postfix

-- calculate operation. use "like" operation instead "IN" for "char" field
SELECT @OPERATION = CASE WHEN LTRIM(@OPERATION) = N'IN' AND @CHARCONDITIONFLAG = 1 THEN N'like' ELSE @OPERATION END

-- initialize sql conditions and parameters
SELECT
@CHARCONDITION = N''
,@NUMBERCONDITION = N''
,@PROCPARAMETERLIST = N''
,@DECORATOR = CASE WHEN @CHARCONDITIONFLAG = 1 THEN '''' ELSE '' END
,@POSTFIX = CASE WHEN CHARINDEX(N'like', @OPERATION) &gt; 0 THEN N' ESCAPE N''''~'''' ' ELSE N'' END

FETCH NEXT FROM @VALUES_CURSOR INTO @VALUE, @NAME

---------- cycle by values --------
WHILE @@FETCH_STATUS = 0
BEGIN
--increment parameter index
SELECT @LASTPARAMETERINDEX = @LASTPARAMETERINDEX + 1

DECLARE
@PARAMETERNAME nvarchar(MAX) -- sql parameter name
,@PARAMETERVALUE nvarchar(max) -- parameter value
,@SQ nvarchar(1) -- char constant

SELECT
@PARAMETERNAME =
CASE
WHEN @ISPROCEDURE = 1
THEN REPLACE(N'@{0}', N'{0}', @NAME)
ELSE REPLACE(N'@P{0}', N'{0}', @LASTPARAMETERINDEX)
END
,@SQ = N''''

IF @ISPROCEDURE = 1
BEGIN
-- procedure. create parameter list
SELECT @PROCPARAMETERLIST = @PROCPARAMETERLIST +
REPLACE(REPLACE(N'{0}{1}',
N'{0}',CASE WHEN LEN(@PROCPARAMETERLIST) &gt; 0 THEN N',' ELSE '' END),
N'{1}',@PARAMETERNAME)
-- get parameter type
SELECT @FIELDTYPE = APM.GetProcParameterTypeName(@ENTITY, @PARAMETERNAME)
IF @FIELDTYPE IS NULL
BEGIN
-- parameter type is not found, raise exception
RAISERROR(N'Parameter "%s" for stored procedure "%s" is not defined.', 16, 1, @PARAMETERNAME, @ENTITY)
RETURN
END
-- setup char condition flag if parameter type is char type
SELECT @CHARCONDITIONFLAG = CASE WHEN CHARINDEX(N'char', @FIELDTYPE) &gt; 0 THEN 1 ELSE 0 END
--decorator value
SELECT @DECORATOR = CASE WHEN @CHARCONDITIONFLAG = 1 THEN '''' ELSE '' END
END

-- calcualte parameter value as decorator + value + decorator
-- use calculate expression 'dbId-value' as value for 'rowguid' field
-- for char parameter value use encoding for char '''
SELECT @PARAMETERVALUE = REPLACE(REPLACE(REPLACE(
N'{0}{1}{2}',
N'{0}',@DECORATOR),
N'{1}',
CASE @FIELD
WHEN N'ROWGUID'
THEN
REPLACE(REPLACE(N'{0}-{1}',
N'{0}', @DBID)
,N'{1}', @VALUE)
ELSE
CASE
WHEN @CHARCONDITIONFLAG = 1
THEN replace(@VALUE, @SQ, @SQ + @SQ)
ELSE @VALUE
END
END
),
N'{2}',@DECORATOR)

-- create char sql condition or non char sql condition ([field] operator [parameter]) ('where' clause)
-- for char condition using 'or' otherwise ','
SELECT
@CHARCONDITION = @CHARCONDITION + REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(CONVERT(nvarchar(MAX),
N' {0} {1} {2} {3} {4}'),
N'{0}',CASE WHEN LEN(@CHARCONDITION) &gt; 0 THEN N' OR ' ELSE N'' END),
N'{1}',@FIELD),
N'{2}',@OPERATION),
N'{3}',@PARAMETERNAME),
N'{4}',@POSTFIX)
,@NUMBERCONDITION = @NUMBERCONDITION + REPLACE(REPLACE(CONVERT(nvarchar(MAX),
N'{0}{1}'),
N'{0}',CASE WHEN LEN(@NUMBERCONDITION) &gt; 0 THEN N',' ELSE '' END),

N'{1}',@PARAMETERNAME)
SELECT
-- create parameter list ([parameter] [parameter type],[parameter] [parameter type],etc)
--use nvarchar(255) for 'eventdetail' entity because field type is not defined for this entity
@PARAMS = @PARAMS + REPLACE(REPLACE(REPLACE(CONVERT(nvarchar(MAX),
N'{0}{1} {2}'),
N'{0}',CASE WHEN LEN(@PARAMS) &gt; 0 THEN N',' ELSE N'' END),
N'{1}',@PARAMETERNAME),
N'{2}',CASE WHEN @ENTITY=@EVENTDETAILENTITY OR @ENTITY=@CSEVENTDETAILENTITY THEN N'nvarchar(255)' ELSE @FIELDTYPE END)

-- create parameter value list ([parameter value], [parameter value],etc)
,@PARAMSVALUES = @PARAMSVALUES + REPLACE(REPLACE(CONVERT(nvarchar(MAX),
N'{0}{1}'),
N'{0}',CASE WHEN LEN(@PARAMSVALUES) &gt; 0
THEN
CASE
WHEN @CHARCONDITIONFLAG = 1
THEN N',N'
ELSE N','
END
ELSE
CASE
WHEN @CHARCONDITIONFLAG = 1
THEN N'N'
ELSE N''
END
END
),
N'{1}',@PARAMETERVALUE)

FETCH NEXT FROM @VALUES_CURSOR INTO @VALUE, @NAME
END
CLOSE @VALUES_CURSOR
DEALLOCATE @VALUES_CURSOR

-- finished create sql condition for non char field
-- ([field] [NOT] @OPERATION [(number condition)])
SELECT @NUMBERCONDITION = REPLACE(REPLACE(REPLACE(REPLACE(CONVERT(nvarchar(MAX),
N'{0} {1} {2} ({3})'),
N'{0}', @FIELD),
N'{1}', CASE WHEN @NOTEXPRESSION = 1 THEN N'NOT' ELSE N'' END),
N'{2}', @OPERATION),
N'{3}', @NUMBERCONDITION)

--user numeric or char sql condition or non char condition. it depends on field type
SELECT @CONDITION = @CONDITION + REPLACE(CONVERT(nvarchar(MAX),N'{0} )'),
N'{0}', CASE WHEN @CHARCONDITIONFLAG = 1 THEN @CHARCONDITION ELSE @NUMBERCONDITION END)
--finished processes current expression
--it is need to joined together the same entity except 'eventdetail' entity and stored proc
--for each row from @QUERYSET will be create separate query. All these query will be intersected.
IF EXISTS(
SELECT * FROM @QUERYSET WHERE entity = @ENTITY AND entity != @EVENTDETAILENTITY
AND entity != @CSEVENTDETAILENTITY
) AND (@ISPROCEDURE = 0)
BEGIN
UPDATE @QUERYSET
SET
condition = @CONDITION -- sql condition
,lastParameterIndex = @LASTPARAMETERINDEX -- last parameter index
,params = @PARAMS -- parameter list
,paramsValues = @PARAMSVALUES -- parameter value list
WHERE
entity = @ENTITY
END
ELSE
BEGIN
-- additional processing for 'eventdetail' entity
--The field 'fieldType' of entity mapping table contains filter value
--for field 'name' of 'eventdetail' entity. Therefore for this entity sql condition will be shown as
-- ['name' = 'fieldType' and 'field' operator 'value']
IF @ENTITY = @EVENTDETAILENTITY OR @ENTITY = @CSEVENTDETAILENTITY
BEGIN
-- increment last parameter index
SELECT @LASTPARAMETERINDEX = @LASTPARAMETERINDEX + 1
--calculate parameter name
SELECT @PARAMETERNAME = REPLACE(N'@P{0}', N'{0}', @LASTPARAMETERINDEX)

--add additional filter by 'name' field
SELECT @CONDITION = @CONDITION +
REPLACE(CONVERT(nvarchar(MAX),N' AND NAME={0}'), N'{0}', @PARAMETERNAME)
--field type is not registered. Use nvarchar(50).
SELECT @PARAMS = @PARAMS +
REPLACE(CONVERT(nvarchar(MAX),N',{0} nvarchar(50)'), N'{0}', @PARAMETERNAME)
-- field type from mapping table contains filter value. It always is char value. Use char decorator.
SELECT @PARAMSVALUES = @PARAMSVALUES +
REPLACE(CONVERT(nvarchar(MAX),N',{0}'), N'{0}',QUOTENAME(@FIELDTYPE, ''''))
END
-- for 'eventdetail' entity always use new query.
INSERT @QUERYSET (entity, condition, lastParameterIndex, params, paramsValues, procParameterList)
VALUES(@ENTITY, @CONDITION, @LASTPARAMETERINDEX, @PARAMS, @PARAMSVALUES, @PROCPARAMETERLIST)
END

--- Get next expression ----
FETCH NEXT FROM expressions_cursor
INTO @EXPRESSION
END
CLOSE expressions_cursor
DEALLOCATE expressions_cursor

-- It is need to add action filter and seviewer database filter to sql condition for each query
---------- added action fields ------

DECLARE
@RESULT_CURSOR CURSOR
,@ID int -- unique identifier for current query. It use because entity can be not unique

-- prepare iteration by each query
SET @RESULT_CURSOR = CURSOR STATIC FOR
SELECT id, entity, condition, params, paramsValues FROM @QUERYSET

OPEN @RESULT_CURSOR

--get current query (unique identifier, entity name, sql condition ('where' clause, parameter list, parameter value list)
FETCH NEXT FROM @RESULT_CURSOR INTO @ID, @ENTITY, @CONDITION, @PARAMS, @PARAMSVALUES

WHILE @@FETCH_STATUS = 0
BEGIN

DECLARE
@ACTIONPARAMS nvarchar(max) --action parameters
,@ACTIONPARAMSVALUES nvarchar(max) --action parameter value
,@ACTIONPARAMETER nvarchar(50) --action parameter name
,@ACTIONFIELD nvarchar(50) -- action field
,@ACTIONENTITY nvarchar(max) -- action entity
,@ACTIONCONDITION nvarchar(MAX) -- action sql condition
,@ACTION_CURSOR CURSOR --It is need for several actions

-- prepare condition for adding action filter
SELECT @ACTIONCONDITION = N'', @CONDITION = @CONDITION + CONVERT(nvarchar(MAX),N' AND (')
--Get action filters. Now there is one action filter
EXEC APM.PMActionQuery @RULEDESCRIPTION, @CLIENT, @DBID, 0, @ACTION_CURSOR OUTPUT

FETCH NEXT FROM @ACTION_CURSOR
INTO @ACTIONPARAMETER, @ACTIONFIELD, @ACTIONPARAMS, @ACTIONPARAMSVALUES,@ACTIONENTITY

WHILE @@FETCH_STATUS = 0
BEGIN
-- create action sql condition ([actionField] != [actionParameter])
--It is need to add filter by seviewer database (SEVIEWERDBID = [seviewer database identifier])
SELECT
@ACTIONCONDITION = @ACTIONCONDITION +
REPLACE(REPLACE(REPLACE(CONVERT(nvarchar(MAX),N' {0} {1} != {2} AND SEVIEWERDBID = @DBID'),
N'{0}', CASE WHEN LEN(@ACTIONCONDITION) &gt; 0 THEN N'OR' ELSE N'' END),
N'{1}', @ACTIONFIELD),
N'{2}', @ACTIONPARAMETER)

--Get next action condition. Now it will be return empty row because use only one action
FETCH NEXT FROM @ACTION_CURSOR
INTO @ACTIONPARAMETER, @ACTIONFIELD, @ACTIONPARAMS, @ACTIONPARAMSVALUES, @ACTIONENTITY
END
CLOSE @ACTION_CURSOR
DEALLOCATE @ACTION_CURSOR

-- join expression sql condition and action sql condition
-- Now action parameter value and database identifier are not included in parameter value list
-- These parameter values (action value and database identifier) will be added to parameter values during execution
-- intersect command
SELECT @CONDITION = @CONDITION + @ACTIONCONDITION + CONVERT(nvarchar(MAX),N')')

--update condition for current query by unique identifier
UPDATE @QUERYSET
SET condition = @CONDITION
WHERE
id = @ID

-- get next query
FETCH NEXT FROM @RESULT_CURSOR INTO @ID, @ENTITY, @CONDITION, @PARAMS, @PARAMSVALUES
END

-- create result cursor
SET @QUERY_CURSOR = CURSOR STATIC FORWARD_ONLY FOR

SELECT
entity -- entity name
,condition -- sql condition
,params -- parameter list
,paramsValues -- parameter value list
,lastParameterIndex -- last parameter index
,procParameterList --proc parameter list
FROM
@QUERYSET

-- open result query
OPEN @QUERY_CURSOR

END TRY
BEGIN CATCH
IF (@@TRANCOUNT &gt; 0)
ROLLBACK TRAN

SELECT
@ERRORNUMBER = ERROR_NUMBER()
,@ERRORSEVERITY = ERROR_SEVERITY()
,@ERRORSTATE = ERROR_STATE()
,@ERRORLINE = ERROR_LINE()
,@ERRORPROCEDURE = ISNULL(ERROR_PROCEDURE(), '-')
,@ERRORMESSAGETEXT = ERROR_MESSAGE()

SET @ERRORIND = 1
END CATCH

IF (@ERRORIND = 1)
BEGIN
IF CURSOR_STATUS('global', 'expressions_cursor') IN (0,1)
CLOSE expressions_cursor
IF CURSOR_STATUS('global', 'expressions_cursor') = -1
DEALLOCATE expressions_cursor

IF CURSOR_STATUS('variable', '@ACTION_CURSOR') IN (0,1)
CLOSE @ACTION_CURSOR
IF CURSOR_STATUS('variable', '@ACTION_CURSOR') = -1
DEALLOCATE @ACTION_CURSOR

IF CURSOR_STATUS('global', 'expressions_cursor') IN (0,1)
CLOSE result_cursor
IF CURSOR_STATUS('global', 'expressions_cursor') = -1
DEALLOCATE result_cursor

DECLARE
@ADJUSTEDERRORSEVERITY INT

SET @ADJUSTEDERRORSEVERITY = CASE
WHEN @ERRORSEVERITY &gt; 18 THEN 18
ELSE @ERRORSEVERITY
END

RAISERROR (@ERRORMESSAGETEXT, @ADJUSTEDERRORSEVERITY, 1
,@ERRORNUMBER
,@ERRORSEVERITY
,@ERRORSTATE
,@ERRORPROCEDURE
,@ERRORLINE
,@ERRORMESSAGETEXT
)
END
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.PMIntersectExpressionQuery'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.PMIntersectExpressionQuery AS RETURN 1')
END
GO

/******************************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: PMIntersectExpressionQuery */
/* INPUT PARAMETERS: */
/* @RULEDESCRIPTION - rule description */
/* @CLIENT - client event flag : 0 - server event 1 - client event */
/* @DBID - seviewer database id. SEviewerDb primary key */
/* OUTPUT PARAMETERS: */
/* @QUERY_CURSOR - result cursor */
/* DESCRIPTION: */
/* It create full sql query for rule. This query intersect all rule expression. Stored procedure are */
/* not supported. It partial implemented. */
/* Result cursor will be contains next fields */
/* --------|---------------|------------|------------------|----------------------|----------------- */
/* entity | sql query | parameters | parameter values | last parameter index | proc parameters */
/* --------|---------------|------------|------------------|----------------------|----------------- */
/* table/ | parameter | parameter | parameter value | | reserved */
/* view/ | query | name | list | | */
/* stored| | parameter | | | */
/* proc | | type | | | */
/* --------|---------------|------------|------------------|----------------------|----------------- */
/******************************************************************************************************/
alter PROCEDURE [APM].[PMIntersectExpressionQuery]
@RULEDESCRIPTION nvarchar(max)
,@CLIENT bit
,@DBID int
,@QUERY_CURSOR CURSOR VARYING OUTPUT
AS
BEGIN
SET NOCOUNT ON;

DECLARE
@ERRORIND BIT
,@ERRORMESSAGE NVARCHAR(4000)
,@ERRORNUMBER INT
,@ERRORSEVERITY INT
,@ERRORSTATE INT
,@ERRORLINE INT
,@ERRORPROCEDURE SYSNAME
,@ERRORMESSAGETEXT NVARCHAR(4000)

SET @ERRORIND = 0

BEGIN TRY

DECLARE
@ENTITY sysname -- entity name
,@CONDITION nvarchar(MAX) -- current sql condition
,@PARAMS nvarchar(MAX) -- parameter list
,@PARAMSVALUES nvarchar(MAX) --parameter value list
,@PROCPARAMETERLIST NVARCHAR(MAX) --reserved
,@LASTPARAMETERINDEX int -- last parameter index
,@QUERY_CUR CURSOR

-- Get queries that will be intercected
EXEC APM.PMExpressionQuery @RULEDESCRIPTION, @CLIENT, @DBID, @QUERY_CUR OUTPUT

--iteration by expression query
FETCH NEXT FROM @QUERY_CUR INTO
@ENTITY, @CONDITION, @PARAMS, @PARAMSVALUES, @LASTPARAMETERINDEX, @PROCPARAMETERLIST

DECLARE
@SQL nvarchar(MAX) -- intersect sql query
,@INTERSECTPARAMS nvarchar(MAX) -- sql parameters for intersect query
,@INTERSECTPARAMSVALUES nvarchar(MAX) -- intersect parameter values


--initialize intersect variables
SELECT @SQL = N'', @INTERSECTPARAMS = N'', @INTERSECTPARAMSVALUES = N''

WHILE @@FETCH_STATUS = 0
BEGIN

IF @CONDITION IS NOT NULL
BEGIN
--create intersect sql query using current expression sql query
SELECT @SQL = @SQL +
REPLACE(REPLACE(REPLACE(CONVERT(nvarchar(max),N'{0} SELECT EVENTID FROM APM.{1} WHERE {2}'),
N'{0}', CASE WHEN LEN(@SQL) &gt; 0 THEN N' INTERSECT' ELSE '' END)
,N'{1}', QUOTENAME(@ENTITY))
,N'{2}', @CONDITION)
--create intercept parameters using current expression sql parameters
SELECT @INTERSECTPARAMS = @INTERSECTPARAMS +
REPLACE(REPLACE(CONVERT(nvarchar(max),N'{0}{1}'),
N'{0}', CASE WHEN LEN(@INTERSECTPARAMS) &gt; 0 THEN N',' ELSE '' END)
,N'{1}', @PARAMS)

--create intersect sql parameter values using current expression parameter values
SELECT @INTERSECTPARAMSVALUES = @INTERSECTPARAMSVALUES +
REPLACE(REPLACE(CONVERT(nvarchar(max),N'{0}{1}'),
N'{0}', CASE WHEN LEN(@INTERSECTPARAMSVALUES) &gt; 0 THEN N',' ELSE '' END)
,N'{1}', @PARAMSVALUES)
END
ELSE
BEGIN
-- stored proc is used if condition is null, now it is not supported, raise exception
RAISERROR (N'The execution of stored procedure is not supported', 16, 1)
RETURN
END

--get next expression query
FETCH NEXT FROM @QUERY_CUR INTO
@ENTITY, @CONDITION, @PARAMS, @PARAMSVALUES, @LASTPARAMETERINDEX, @PROCPARAMETERLIST
END
CLOSE @QUERY_CUR
DEALLOCATE @QUERY_CUR

-- intersect query is created. It is need to add action and database id parameters
DECLARE
@ACTIONPARAMS nvarchar(max) -- action parameters including database id parameter.
,@ACTIONPARAMSVALUES nvarchar(max) -- action parameter values including database id parameter
,@ACTIONPARAMETER nvarchar(50) -- action parameter name. Use only for fetch operation. Don't remove
-- from fetch expression
,@ACTIONFIELD nvarchar(50) -- action field. Use only for fetch operation. Don't remove
-- from fetch expression
,@ACTIONENTITY nvarchar(max) -- action entity. Use only for fetch operation. Don't remove
-- from fetch expression
,@ACTION_CURSOR CURSOR -- action query. It is only one record now.

-- Get action and database id parameters
EXEC APM.PMActionQuery @RULEDESCRIPTION, @CLIENT, @DBID, 0, @ACTION_CURSOR OUTPUT

-- fetch action and database id parameters
FETCH NEXT FROM @ACTION_CURSOR
INTO @ACTIONPARAMETER, @ACTIONFIELD, @ACTIONPARAMS, @ACTIONPARAMSVALUES,@ACTIONENTITY

WHILE @@FETCH_STATUS = 0
BEGIN
SELECT
-- added to intersect parameters
@INTERSECTPARAMS = @INTERSECTPARAMS + REPLACE(CONVERT(nvarchar(max),N',{0}'), N'{0}',@ACTIONPARAMS)
-- added to intersect parameter values
,@INTERSECTPARAMSVALUES = @INTERSECTPARAMSVALUES + REPLACE(CONVERT(nvarchar(max),N',{0}'), N'{0}',@ACTIONPARAMSVALUES)

-- fetch next action and database id parameters.
FETCH NEXT FROM @ACTION_CURSOR
INTO @ACTIONPARAMETER, @ACTIONFIELD, @ACTIONPARAMS, @ACTIONPARAMSVALUES, @ACTIONENTITY
END
CLOSE @ACTION_CURSOR
DEALLOCATE @ACTION_CURSOR

--create result sql query
DECLARE
@QUERYSET TABLE
(
entity SYSNAME --view/table or stored proc. reserved
,condition NVARCHAR(MAX) --sql query
,params NVARCHAR(MAX) -- sql parameter list
,paramsValues NVARCHAR(MAX) -- sql parameter values
,lastParameterIndex int -- reserved
,procParameterList NVARCHAR(max) -- reserved
)

INSERT @QUERYSET
(
entity,
condition,
params,
paramsValues,
lastParameterIndex,
procParameterList
)
SELECT
@ENTITY --view/table or stored proc. reserved
,@SQL --sql query
,@INTERSECTPARAMS -- sql parameter list
,@INTERSECTPARAMSVALUES -- sql parameter values
,@LASTPARAMETERINDEX -- reserved
,@PROCPARAMETERLIST -- reserved

--create result cursor
SET @QUERY_CURSOR = CURSOR STATIC FOR SELECT * FROM @QUERYSET
--open cursor
OPEN @QUERY_CURSOR

END TRY
BEGIN CATCH
IF (@@TRANCOUNT &gt; 0)
ROLLBACK TRAN

SELECT
@ERRORNUMBER = ERROR_NUMBER()
,@ERRORSEVERITY = ERROR_SEVERITY()
,@ERRORSTATE = ERROR_STATE()
,@ERRORLINE = ERROR_LINE()
,@ERRORPROCEDURE = ISNULL(ERROR_PROCEDURE(), '-')
,@ERRORMESSAGETEXT = ERROR_MESSAGE()

SET @ERRORIND = 1
END CATCH

IF (@ERRORIND = 1)
BEGIN
IF CURSOR_STATUS('variable', '@QUERY_CUR') IN (0,1)
CLOSE @QUERY_CUR
IF CURSOR_STATUS('variable', '@QUERY_CUR') = -1
DEALLOCATE @QUERY_CUR

DECLARE
@ADJUSTEDERRORSEVERITY INT

SET @ADJUSTEDERRORSEVERITY = CASE
WHEN @ERRORSEVERITY &gt; 18 THEN 18
ELSE @ERRORSEVERITY
END


RAISERROR (@ERRORMESSAGETEXT, @ADJUSTEDERRORSEVERITY, 1
,@ERRORNUMBER
,@ERRORSEVERITY
,@ERRORSTATE
,@ERRORPROCEDURE
,@ERRORLINE
,@ERRORMESSAGETEXT
)
END
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.PMQueryForRule'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.PMQueryForRule AS RETURN 1')
END
GO

/******************************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: PMQueryForRule */
/* INPUT PARAMETERS: */
/* @RULEDESCRIPTION - rule description */
/* @CLIENT - client event flag : 0 - server event 1 - client event */
/* @DBID - seviewer database id. SEviewerDb primary key */
/* @CALCULATETOTAL - calculate total flag (1- it is need to calculate count of records */
/* 0- it is need to fetch records) */
/* @ROWSPERITERATION - number of records that is need to fetch */
/* @DEBUG - 0-trace information will be not print */
/* 1-trace information will be print */
/* DESCRIPTION: */
/* Calculate total records or fetch records that will be apply by rule. */
/* It is need external temporary tables #QUERYTEXT and #RESULTTABLE for execute. */
/* #QUERYTEXT table is used for cache sql query (decrease execution count of xml operations). */
/* Total count or records will be inserted into the #RESULT table */
/******************************************************************************************************/
alter PROCEDURE [APM].[PMQueryForRule]
@RULEDESCRIPTION nvarchar(max)
,@CLIENT bit
,@DBID int
,@CALCULATETOTAL bit
,@ROWSPERITERATION int
,@DEBUG bit = 0
AS
BEGIN
SET NOCOUNT ON;

DECLARE
@ERRORIND BIT
,@ERRORMESSAGE NVARCHAR(4000)
,@ERRORNUMBER INT
,@ERRORSEVERITY INT
,@ERRORSTATE INT
,@ERRORLINE INT
,@ERRORPROCEDURE SYSNAME
,@ERRORMESSAGETEXT NVARCHAR(4000)

SET @ERRORIND = 0

BEGIN TRY

DECLARE
@ENTITY sysname -- entity name or stored proc name
,@CONDITION nvarchar(MAX) -- sql query for execution
,@PARAMS nvarchar(MAX) -- sql query parameter list
,@PARAMSVALUES nvarchar(MAX) -- sql query parameter values
,@PROCPARAMETERLIST NVARCHAR(MAX) -- reserved
,@LASTPARAMETERINDEX int -- reserved
,@QUERY_CUR CURSOR -- query cursor

DECLARE
@SQL nvarchar(MAX)

-- cache is empty ?
IF NOT EXISTS(SELECT * FROM #QUERYTEXT WHERE UPDATESQL = 0)
BEGIN
---create intersect query that will be execute
EXEC APM.PMIntersectExpressionQuery @RULEDESCRIPTION, @CLIENT, @DBID, @QUERY_CUR OUTPUT

-- get intersect query
FETCH NEXT FROM @QUERY_CUR INTO
@ENTITY, @CONDITION, @PARAMS, @PARAMSVALUES, @LASTPARAMETERINDEX, @PROCPARAMETERLIST

WHILE @@FETCH_STATUS = 0
BEGIN
DECLARE
@COMMAND nvarchar(MAX)

--stored proc ?
IF @CONDITION IS NOT NULL
-- create sql for extract (calculate total) event id corresponding rule
SELECT @COMMAND =
REPLACE(REPLACE(CONVERT(nvarchar(max),N'SELECT {0} FROM ({1}) AS A'),
N'{0}', CASE
WHEN @CALCULATETOTAL = 0 THEN REPLACE(N'TOP({0}) A.EVENTID', N'{0}', @ROWSPERITERATION)
ELSE N'COUNT(*)'
END)
,N'{1}', @CONDITION)
ELSE -- stored proc
SELECT @COMMAND =
REPLACE(REPLACE(N'EXEC APM.{0} {1}',
N'{0}', @ENTITY),
N'{1}', @PROCPARAMETERLIST)
-- create sql for call sp_execute that will execute intersect query
SELECT @SQL = REPLACE(REPLACE(REPLACE(CONVERT(nvarchar(max),N'sp_executesql N''{0}'', N''{1}'', {2}'),
N'{0}',@COMMAND),
N'{1}',@PARAMS),
N'{2}',@PARAMSVALUES)
-- save result query to cache
INSERT #QUERYTEXT(SQLTEXT, UPDATESQL) SELECT @SQL, 0

IF @DEBUG = 1
BEGIN
PRINT @SQL
END

--fetch next intersect query
FETCH NEXT FROM @QUERY_CUR INTO
@ENTITY, @CONDITION, @PARAMS, @PARAMSVALUES, @LASTPARAMETERINDEX, @PROCPARAMETERLIST;
-- There is additional query only if it contains stored proc. Now stored proc is not supported
IF @@FETCH_STATUS = 0
BEGIN
-- query contains stored proc, raise exception
RAISERROR (N'The execution of stored procedure is not supported', 16, 1)
RETURN
END

END
CLOSE @QUERY_CUR
DEALLOCATE @QUERY_CUR

END

--get result query from cache
SELECT TOP (1) @SQL = SQLTEXT FROM #QUERYTEXT WHERE UPDATESQL = 0

--save result of query execution to external temporary table
INSERT #RESULTTABLE EXEC sp_executesql @SQL

END TRY
BEGIN CATCH
IF (@@TRANCOUNT &gt; 0)
ROLLBACK TRAN

SELECT
@ERRORNUMBER = ERROR_NUMBER()
,@ERRORSEVERITY = ERROR_SEVERITY()
,@ERRORSTATE = ERROR_STATE()
,@ERRORLINE = ERROR_LINE()
,@ERRORPROCEDURE = ISNULL(ERROR_PROCEDURE(), '-')
,@ERRORMESSAGETEXT = ERROR_MESSAGE()

SET @ERRORIND = 1
END CATCH

IF (@ERRORIND = 1)
BEGIN
IF CURSOR_STATUS('variable', '@QUERY_CUR') IN (0,1)
CLOSE @QUERY_CUR
IF CURSOR_STATUS('variable', '@QUERY_CUR') = -1
DEALLOCATE @QUERY_CUR

DECLARE
@ADJUSTEDERRORSEVERITY INT

SET @ADJUSTEDERRORSEVERITY = CASE
WHEN @ERRORSEVERITY &gt; 18 THEN 18
ELSE @ERRORSEVERITY
END

IF @DEBUG = 0
PRINT @SQL

RAISERROR (@ERRORMESSAGETEXT, @ADJUSTEDERRORSEVERITY, 1
,@ERRORNUMBER
,@ERRORSEVERITY
,@ERRORSTATE
,@ERRORPROCEDURE
,@ERRORLINE
,@ERRORMESSAGETEXT
)
END
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.PMApplyActionsToDb'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.PMApplyActionsToDb AS RETURN 1')
END
GO

/******************************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: PMApplyActionsToDb */
/* INPUT PARAMETERS: */
/* @RULEDESCRIPTION - rule description */
/* @CLIENT - client event flag : 0 - server event 1 - client event */
/* @DBID - seviewer database id. SEviewerDb primary key */
/* @DEBUG - 0-trace information will be not print */
/* 1-trace information will be print */
/* OUTPUT PARAMETERS: */
/* @PROGRESS - rows affected */
/* DESCRIPTION: */
/* Update records corresponding rule. */
/* It is need external temporary tables #QUERYTEXT and #RESULTTABLE for execute. */
/* #QUERYTEXT table is used for cache sql query (decrease execution count of xml operations). */
/* #RESULT table contains event id of records of event table that will be updated */
/******************************************************************************************************/
alter PROCEDURE [APM].[PMApplyActionsToDb]
@RULEDESCRIPTION nvarchar(max)
,@CLIENT bit
,@DBID int
,@DEBUG bit = 0
,@PROGRESS int OUTPUT
AS
BEGIN
SET NOCOUNT ON;

DECLARE
@ERRORIND BIT
,@ERRORMESSAGE NVARCHAR(4000)
,@ERRORNUMBER INT
,@ERRORSEVERITY INT
,@ERRORSTATE INT
,@ERRORLINE INT
,@ERRORPROCEDURE SYSNAME
,@ERRORMESSAGETEXT NVARCHAR(4000)

SET @ERRORIND = 0

BEGIN TRY

DECLARE
@SQL nvarchar(max) -- update sql

-- check cache
IF NOT EXISTS(SELECT * FROM #QUERYTEXT WHERE UPDATESQL = 1)
BEGIN
-- update query not found
-- create update query

DECLARE
@ACTIONPARAMS nvarchar(max) -- action parameter and database id parameter
,@ACTIONPARAMSVALUES nvarchar(max) -- action parameter value and database id parameter value
,@ACTIONPARAMETER nvarchar(50) -- action parameter
,@ACTIONFIELD nvarchar(50) -- action field
,@ACTIONENTITY nvarchar(max) -- action entity (table/view or stored proc)
,@ACTION_CURSOR CURSOR -- action cursor for fetching action parameters, etc

DECLARE
@SETEXPRESSION nvarchar(max)
,@PARAMS nvarchar(MAX)
,@PARAMSVALUES nvarchar(max)

-- get action cursor corresponding rule
EXEC APM.PMActionQuery @RULEDESCRIPTION, @CLIENT, @DBID, 0, @ACTION_CURSOR OUTPUT

-- initialize action parameters
SELECT @SETEXPRESSION = N'', @PARAMS = N'', @PARAMSVALUES = N''

-- fetch action parameters
FETCH NEXT FROM @ACTION_CURSOR
INTO @ACTIONPARAMETER, @ACTIONFIELD, @ACTIONPARAMS, @ACTIONPARAMSVALUES, @ACTIONENTITY

WHILE @@FETCH_STATUS = 0
BEGIN
SELECT

--create 'set' clause for update sql ([action field] = [action parameter])
@SETEXPRESSION = @SETEXPRESSION + REPLACE(REPLACE(REPLACE(CONVERT(nvarchar(max),N'{0}e.{1}={2}'),
N'{0}',CASE WHEN LEN(@SETEXPRESSION) &gt; 0 THEN N',' ELSE N'' END),
N'{1}',@ACTIONFIELD),
N'{2}',@ACTIONPARAMETER)

--create parameters for update sql
,@PARAMS = @PARAMS +
REPLACE(REPLACE(CONVERT(nvarchar(max),N'{0}{1}'),
N'{0}',CASE WHEN LEN(@PARAMS) &gt; 0 THEN N',' ELSE N'' END),
N'{1}', @ACTIONPARAMS)
--create parameter values for update sql
,@PARAMSVALUES = @PARAMSVALUES + REPLACE(REPLACE(CONVERT(nvarchar(max),N'{0}{1}'),
N'{0}',CASE WHEN LEN(@PARAMSVALUES) &gt; 0 THEN N',' ELSE N'' END),
N'{1}',@ACTIONPARAMSVALUES)
--fetch next action parameters. Now should be empty because use only one action.
FETCH NEXT FROM @ACTION_CURSOR
INTO @ACTIONPARAMETER, @ACTIONFIELD, @ACTIONPARAMS, @ACTIONPARAMSVALUES, @ACTIONENTITY
END
CLOSE @ACTION_CURSOR
DEALLOCATE @ACTION_CURSOR

DECLARE
@COMMAND nvarchar(max) -- update command
,@ROWSAFFECTED int -- rows affected

-- create update command using external temporary table
SELECT @COMMAND =
REPLACE(REPLACE(CONVERT(nvarchar(max),
N'UPDATE e
SET {0}
OUTPUT INSERTED.EventId, INSERTED.pmstatus INTO #STATUSTABLE
FROM APM.{1} e
JOIN #RESULTTABLE r ON r.EVENTID = e.EVENTID
SET @ROWSAFFECTED = @@ROWCOUNT
'),
N'{0}', @SETEXPRESSION),
N'{1}', @ACTIONENTITY)
-- add sp_execute call for execution update command
SELECT @SQL = REPLACE(REPLACE(REPLACE(CONVERT(nvarchar(max),N'exec sp_executesql N''{0}'', N''{1}'', {2}'),
N'{0}',@COMMAND),
N'{1}',@PARAMS + N',@ROWSAFFECTED int OUTPUT'),
N'{2}',@PARAMSVALUES + N',@ROWSAFFECTED=@ROWSAFFECTED OUTPUT')

IF @DEBUG = 1
PRINT @SQL

-- insert sql command into cache
INSERT #QUERYTEXT(SQLTEXT, UPDATESQL, PMSTATUS) SELECT @SQL, 1, @ACTIONPARAMSVALUES
END

DECLARE
@PMSTATUS nvarchar(MAX)

-- get query from cache
SELECT TOP (1) @SQL = SQLTEXT, @PMSTATUS = PMSTATUS FROM #QUERYTEXT WHERE UPDATESQL = 1

CREATE TABLE #STATUSTABLE (EVENTID int, PMSTATUS tinyint)

-- execute update events corresponding rule
EXEC sp_executesql @SQL,N'@ROWSAFFECTED int OUTPUT',@ROWSAFFECTED = @ROWSAFFECTED OUTPUT

IF @DEBUG = 1
PRINT N'Rows affected: ' + CAST(@ROWSAFFECTED AS nvarchar(10))

IF @ROWSAFFECTED &gt; 0
BEGIN
--create event trace
EXEC APM.PMCREATEEVENTTRACES @CLIENT = @CLIENT, @DATA = @RULEDESCRIPTION
END
--save rows affected
SELECT @PROGRESS = @ROWSAFFECTED
END TRY
BEGIN CATCH
IF (@@TRANCOUNT &gt; 0)
ROLLBACK TRAN

SELECT
@ERRORNUMBER = ERROR_NUMBER()
,@ERRORSEVERITY = ERROR_SEVERITY()
,@ERRORSTATE = ERROR_STATE()
,@ERRORLINE = ERROR_LINE()
,@ERRORPROCEDURE = ISNULL(ERROR_PROCEDURE(), '-')
,@ERRORMESSAGETEXT = ERROR_MESSAGE()

SET @ERRORIND = 1
END CATCH
IF (@ERRORIND = 1)
BEGIN
IF CURSOR_STATUS('variable', '@ACTION_CURSOR') IN (0,1)
CLOSE @ACTION_CURSOR
IF CURSOR_STATUS('variable', '@ACTION_CURSOR') = -1
DEALLOCATE @ACTION_CURSOR
DECLARE
@ADJUSTEDERRORSEVERITY INT

SET @ADJUSTEDERRORSEVERITY = CASE
WHEN @ERRORSEVERITY &gt; 18 THEN 18
ELSE @ERRORSEVERITY
END

IF @DEBUG = 0
PRINT @SQL

RAISERROR (@ERRORMESSAGETEXT, @ADJUSTEDERRORSEVERITY, 1
,@ERRORNUMBER
,@ERRORSEVERITY
,@ERRORSTATE
,@ERRORPROCEDURE
,@ERRORLINE
,@ERRORMESSAGETEXT
)
END
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.PMApplyToDbForEventType'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.PMApplyToDbForEventType AS RETURN 1')
END
GO

/******************************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: PMApplyToDbForEventType */
/* INPUT PARAMETERS: */
/* @CALCULATETOTAL - calculate total flag (1- it is need to calculate count of records */
/* 0- it is need to fetch records) */
/* @CLIENT - client event flag : 0 - server event 1 - client event */
/* @DBID - seviewer database id. SEviewerDb primary key */
/* @RULEDESCRIPTION - rule description */
/* @ROWSPERITERATION - number of records that is need to fetch */
/* @ROWSPERREQUEST - number of records that is need to process for one call of stored */
/* - procedure */
/* @DEBUG - 0-trace information will be not print */
/* 1-trace information will be print */
/* OUTPUT PARAMETERS: */
/* @ROWSAFFECTED - rows affected if calculate total flag equal zero */
/* @TOTAL - calculate row count if calculate total flag equal one */
/* DESCRIPTION: */
/* Calculate total records or update records that will be apply by rule. */
/******************************************************************************************************/
alter PROCEDURE [APM].[PMApplyToDbForEventType]
@CALCULATETOTAL bit
,@CLIENT bit
,@DBID int
,@RULEDESCRIPTION nvarchar(MAX)
,@ROWSPERITERATION int
,@ROWSPERREQUEST int
,@DEBUG bit
,@ROWSAFFECTED int OUTPUT
,@TOTAL int OUTPUT
AS
BEGIN
SET NOCOUNT ON;

DECLARE
@ERRORIND BIT
,@ERRORMESSAGE NVARCHAR(4000)
,@ERRORNUMBER INT
,@ERRORSEVERITY INT
,@ERRORSTATE INT
,@ERRORLINE INT
,@ERRORPROCEDURE SYSNAME
,@ERRORMESSAGETEXT NVARCHAR(4000)

SET @ERRORIND = 0

BEGIN TRY

-- Initialize output parameters
SELECT @TOTAL = 0, @ROWSAFFECTED = 0

-- It is need external temporary tables for execute.
--It is need for saving results
CREATE TABLE #RESULTTABLE (EVENTID int)
--It is need for cache sql query
CREATE TABLE #QUERYTEXT (SQLTEXT nvarchar(max), UPDATESQL bit, PMSTATUS nvarchar(MAX))

IF @CALCULATETOTAL = 1
BEGIN
--Calculate total
EXEC APM.PMQueryForRule
@RULEDESCRIPTION = @RULEDESCRIPTION
,@CLIENT = @CLIENT
,@DBID = @DBID
,@CALCULATETOTAL = @CALCULATETOTAL
,@ROWSPERITERATION = @ROWSPERITERATION
,@DEBUG = @DEBUG
--EventId contains result
SELECT @TOTAL = EVENTID FROM #RESULTTABLE
END
IF @CALCULATETOTAL = 0
BEGIN
--Update records
DECLARE @CURRENTAFFECTED int
--Iteration by "rows per iteration"
WHILE @ROWSAFFECTED &lt; @ROWSPERREQUEST
BEGIN
--Fill #RESULT table
EXEC APM.PMQueryForRule
@RULEDESCRIPTION = @RULEDESCRIPTION
,@CLIENT = @CLIENT
,@DBID = @DBID
,@CALCULATETOTAL = @CALCULATETOTAL
,@ROWSPERITERATION = @ROWSPERITERATION
,@DEBUG = @DEBUG
-- #RESULT table contains set of eventId referencing to the event records that will be updated
EXEC APM.PMApplyActionsToDb
@RULEDESCRIPTION = @RULEDESCRIPTION
,@CLIENT = @CLIENT
,@DBID = @DBID
,@DEBUG = @DEBUG
,@PROGRESS = @CURRENTAFFECTED OUTPUT

-- update rows affected counter
SELECT @ROWSAFFECTED = @ROWSAFFECTED + @CURRENTAFFECTED

--get out if current rows affected less rows per iteration because rows per iteration records should be updated
IF @CURRENTAFFECTED &lt; @ROWSPERITERATION
BREAK
-- truncate temporary table for next iteration
TRUNCATE TABLE #RESULTTABLE
END
END
END TRY
BEGIN CATCH
IF (@@TRANCOUNT &gt; 0)
ROLLBACK TRAN

SELECT
@ERRORNUMBER = ERROR_NUMBER()
,@ERRORSEVERITY = ERROR_SEVERITY()
,@ERRORSTATE = ERROR_STATE()
,@ERRORLINE = ERROR_LINE()
,@ERRORPROCEDURE = ISNULL(ERROR_PROCEDURE(), '-')
,@ERRORMESSAGETEXT = ERROR_MESSAGE()

SET @ERRORIND = 1
END CATCH
IF (@ERRORIND = 1)
BEGIN
DECLARE
@ADJUSTEDERRORSEVERITY INT

SET @ADJUSTEDERRORSEVERITY = CASE
WHEN @ERRORSEVERITY &gt; 18 THEN 18
ELSE @ERRORSEVERITY
END


RAISERROR (@ERRORMESSAGETEXT, @ADJUSTEDERRORSEVERITY, 1
,@ERRORNUMBER
,@ERRORSEVERITY
,@ERRORSTATE
,@ERRORPROCEDURE
,@ERRORLINE
,@ERRORMESSAGETEXT
)
END
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.PMApplyToDb'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.PMApplyToDb AS RETURN 1')
END
GO

/******************************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: PMApplyToDb */
/* INPUT PARAMETERS: */
/* @CALCULATETOTAL - calculate total flag (1- it is need to calculate count of records */
/* 0- it is need to fetch records) */
/* @RULEDESCRIPTION - rule description */
/* @ROWSPERITERATION - number of records that is need to fetch */
/* @ROWSPERREQUEST - number of records that is need to process for one call of stored */
/* @TRACELEVEL - trace level (4 - detail trace, other - reserved) */
/* OUTPUT PARAMETERS: */
/* @ROWSAFFECTED - rows affected if calculate total flag equal zero */
/* @TOTAL - calculate row count if calculate total flag equal one */
/* DESCRIPTION: */
/* Calculate total records or update records that will be apply by rule. It call internal stored */
/* procedure for server and client events. */
/******************************************************************************************************/
alter PROCEDURE [APM].[PMApplyToDb]
@CALCULATETOTAL bit
,@RULEDESCRIPTION nvarchar(MAX)
,@ROWSPERITERATION int
,@ROWSPERREQUEST int
,@TRACELEVEL int
,@ROWSAFFECTED int OUTPUT
,@TOTAL int OUTPUT
AS
BEGIN
SET NOCOUNT ON

DECLARE
@DEBUG bit -- debug flag (1 - debug, 0 - without debug)
,@SERVERROWSAFFECTED int -- server event records affected
,@SERVERTOTAL int -- server total events (when calculate flag equal one)
,@CLIENTROWSAFFECTED int -- client event records affected
,@CLIENTTOTAL int -- client total events (when calculate flag equal one)
,@DBID int -- seviewer database primary key (seviewerdb table)
,@DBGUID uniqueidentifier -- seviewer database identifier (only records from this seviewer database will be calculated or updated)
,@RULE xml -- untype xml contains rule description

-- implicit conversion to xml
SET @RULE = @RULEDESCRIPTION

--get seviewer database unique identifier
SELECT @DBGUID = @RULE.value('(/rule/@dbid)[1]', 'uniqueidentifier')
--get corresponding seviewer db primary key
SELECT @DBID = SEVIEWERDBID from APM.SEVIEWERDB (NOLOCK)
WHERE DATABASEID = @DBGUID
--database id is exist?
IF @@ROWCOUNT = 0
BEGIN
--No, raise exception
DECLARE
@DATABASEGUIDSTR nvarchar(50)
SELECT @DATABASEGUIDSTR = CAST(@DBGUID as nvarchar(50))
RAISERROR (N'DATABASE Id=''%s'' is not found', 16, 1, @DATABASEGUIDSTR)
RETURN
END

-- debug mode ? (trace level should be equal 4)
SELECT @DEBUG =
CASE
WHEN @TRACELEVEL = 4 THEN 1 ELSE 0
END

-- calculate or update server events
EXECUTE APM.PMApplyToDbForEventType @CALCULATETOTAL = @CALCULATETOTAL, -- bit
@CLIENT = 0, -- bit
@DBID = @DBID, -- int
@RULEDESCRIPTION = @RULEDESCRIPTION, -- nvarchar(max)
@ROWSPERITERATION = @ROWSPERITERATION, -- int
@ROWSPERREQUEST = @ROWSPERREQUEST, -- int
@DEBUG = @DEBUG, -- bit
@ROWSAFFECTED = @SERVERROWSAFFECTED OUTPUT, -- rows affected
@TOTAL = @SERVERTOTAL OUTPUT --total count (if calculate total flag equal 1)

-- calculate or update client events
EXECUTE APM.PMApplyToDbForEventType @CALCULATETOTAL = @CALCULATETOTAL, -- bit
@CLIENT = 1, -- bit
@DBID = @DBID, -- int
@RULEDESCRIPTION = @RULEDESCRIPTION, -- nvarchar(max)
@ROWSPERITERATION = @ROWSPERITERATION, -- int
@ROWSPERREQUEST = @ROWSPERREQUEST, -- int
@DEBUG = @DEBUG, -- bit
@ROWSAFFECTED = @CLIENTROWSAFFECTED OUTPUT, -- rows affected
@TOTAL = @CLIENTTOTAL OUTPUT --total count (if calculate total flag equal 1)

-- update counters
SELECT
@TOTAL = COALESCE(@CLIENTTOTAL,0) + COALESCE(@SERVERTOTAL,0)
,@ROWSAFFECTED = COALESCE(@CLIENTROWSAFFECTED,0) + COALESCE(@SERVERROWSAFFECTED,0)
END
GO
</Install>
<Uninstall>IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
WHERE
CONSTRAINT_SCHEMA = 'APM' AND CONSTRAINT_NAME = 'FK_EVENTDET_REFERENCE_EVENT')
ALTER TABLE APM.EVENTDETAIL DROP CONSTRAINT FK_EVENTDET_REFERENCE_EVENT
GO

IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
WHERE
CONSTRAINT_SCHEMA = 'APM' AND CONSTRAINT_NAME = 'FK_CSEVENTDET_REFERENCE_CSEVENT')
ALTER TABLE APM.CSEVENTDETAIL DROP CONSTRAINT FK_CSEVENTDET_REFERENCE_CSEVENT
GO

IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
WHERE
CONSTRAINT_SCHEMA = 'APM' AND CONSTRAINT_NAME = 'FK_APPLICAT_FK_APPLIC_APPLICAT')
ALTER TABLE APM.APPLICATIONSOURCEMACHINE DROP CONSTRAINT FK_APPLICAT_FK_APPLIC_APPLICAT
GO

IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
WHERE
CONSTRAINT_SCHEMA = 'APM' AND CONSTRAINT_NAME = 'FK_APPLICAT_FK_MACHIN_MACHINE')
ALTER TABLE APM.APPLICATIONSOURCEMACHINE DROP CONSTRAINT FK_APPLICAT_FK_MACHIN_MACHINE
GO

IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
WHERE
CONSTRAINT_SCHEMA = 'APM' AND CONSTRAINT_NAME = 'FK_APPLICAT_FK_SOURCE_SOURCE')
ALTER TABLE APM.APPLICATIONSOURCEMACHINE DROP CONSTRAINT FK_APPLICAT_FK_SOURCE_SOURCE
GO

IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
WHERE
CONSTRAINT_SCHEMA = 'APM' AND CONSTRAINT_NAME = 'FK_CSAJAX_REFERENCE_CSEVENT')
ALTER TABLE APM.CSAJAX DROP CONSTRAINT FK_CSAJAX_REFERENCE_CSEVENT
GO

IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
WHERE
CONSTRAINT_SCHEMA = 'APM' AND CONSTRAINT_NAME = 'FK_CSASYNCA_REFERENCE_CSEVENT')
ALTER TABLE APM.CSASYNCAJAX DROP CONSTRAINT FK_CSASYNCA_REFERENCE_CSEVENT
GO

IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
WHERE
CONSTRAINT_SCHEMA = 'APM' AND CONSTRAINT_NAME = 'FK_CSEVENT_REFERENCE_MACHINE')
ALTER TABLE APM.CSEVENT DROP CONSTRAINT FK_CSEVENT_REFERENCE_MACHINE
GO

IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
WHERE
CONSTRAINT_SCHEMA = 'APM' AND CONSTRAINT_NAME = 'FK_CSEVENT_REFERENCE_SOURCE')
ALTER TABLE APM.CSEVENT DROP CONSTRAINT FK_CSEVENT_REFERENCE_SOURCE
GO

IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
WHERE
CONSTRAINT_SCHEMA = 'APM' AND CONSTRAINT_NAME = 'FK_CSEVENT_REFERENCE_CSEVENTG')
ALTER TABLE APM.CSEVENT DROP CONSTRAINT FK_CSEVENT_REFERENCE_CSEVENTG
GO

IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
WHERE
CONSTRAINT_SCHEMA = 'APM' AND CONSTRAINT_NAME = 'FK_CSEVENT_REFERENCE_IP')
ALTER TABLE APM.CSEVENT DROP CONSTRAINT FK_CSEVENT_REFERENCE_IP
GO

IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
WHERE
CONSTRAINT_SCHEMA = 'APM' AND CONSTRAINT_NAME = 'FK_CSEVENT_USERS')
ALTER TABLE APM.CSEVENT DROP CONSTRAINT FK_CSEVENT_USERS
GO

IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
WHERE
CONSTRAINT_SCHEMA = 'APM' AND CONSTRAINT_NAME = 'FK_CSEXEVEN_REFERENCE_CSEVENT')
ALTER TABLE APM.CSEXEVENT DROP CONSTRAINT FK_CSEXEVEN_REFERENCE_CSEVENT
GO

IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
WHERE
CONSTRAINT_SCHEMA = 'APM' AND CONSTRAINT_NAME = 'FK_CSHEAVIE_REFERENCE_CSEVENT')
ALTER TABLE APM.CSHEAVIESTRESOURCE DROP CONSTRAINT FK_CSHEAVIE_REFERENCE_CSEVENT
GO

IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
WHERE
CONSTRAINT_SCHEMA = 'APM' AND CONSTRAINT_NAME = 'FK_CSJSCRIP_REFERENCE_CSEVENT')
ALTER TABLE APM.CSJSCRIPTEVENT DROP CONSTRAINT FK_CSJSCRIP_REFERENCE_CSEVENT
GO

IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
WHERE
CONSTRAINT_SCHEMA = 'APM' AND CONSTRAINT_NAME = 'FK_CSPAGEEV_REFERENCE_CSEVENT')
ALTER TABLE APM.CSPAGEEVENT DROP CONSTRAINT FK_CSPAGEEV_REFERENCE_CSEVENT
GO

IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
WHERE
CONSTRAINT_SCHEMA = 'APM' AND CONSTRAINT_NAME = 'FK_CSPERIPH_REFERENCE_CSEVENT')
ALTER TABLE APM.CSPERIPHERAL DROP CONSTRAINT FK_CSPERIPH_REFERENCE_CSEVENT
GO

IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
WHERE
CONSTRAINT_SCHEMA = 'APM' AND CONSTRAINT_NAME = 'FK_CSPERIPH_REFERENCE_CSPERIPH')
ALTER TABLE APM.CSPERIPHERALDETAIL DROP CONSTRAINT FK_CSPERIPH_REFERENCE_CSPERIPH
GO

IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
WHERE
CONSTRAINT_SCHEMA = 'APM' AND CONSTRAINT_NAME = 'FK_DATASET_AGGREGATION')
ALTER TABLE APM.DATASET DROP CONSTRAINT FK_DATASET_AGGREGATION
GO

IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
WHERE
CONSTRAINT_SCHEMA = 'APM' AND CONSTRAINT_NAME = 'FK_DATASET_HISTORY')
ALTER TABLE APM.DATASETAGGREGATIONHISTORY DROP CONSTRAINT FK_DATASET_HISTORY
GO

IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
WHERE
CONSTRAINT_SCHEMA = 'APM' AND CONSTRAINT_NAME = 'FK_EVENT_FK_EVENTG_EVENTGRO')
ALTER TABLE APM.EVENT DROP CONSTRAINT FK_EVENT_FK_EVENTG_EVENTGRO
GO


IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
WHERE
CONSTRAINT_SCHEMA = 'APM' AND CONSTRAINT_NAME = 'FK_EVENT_FK_EVENT__IP')
ALTER TABLE APM.EVENT DROP CONSTRAINT FK_EVENT_FK_EVENT__IP
GO

IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
WHERE
CONSTRAINT_SCHEMA = 'APM' AND CONSTRAINT_NAME = 'FK_EVENT_FK_EVENT__SEVIEWER')
ALTER TABLE APM.EVENT DROP CONSTRAINT FK_EVENT_FK_EVENT__SEVIEWER
GO

IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
WHERE
CONSTRAINT_SCHEMA = 'APM' AND CONSTRAINT_NAME = 'FK_EVENT_FK_SOURCE_SOURCE')
ALTER TABLE APM.EVENT DROP CONSTRAINT FK_EVENT_FK_SOURCE_SOURCE
GO

IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
WHERE
CONSTRAINT_SCHEMA = 'APM' AND CONSTRAINT_NAME = 'FK_EVENT_REFERENCE_MACHINE')
ALTER TABLE APM.EVENT DROP CONSTRAINT FK_EVENT_REFERENCE_MACHINE
GO

IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
WHERE
CONSTRAINT_SCHEMA = 'APM' AND CONSTRAINT_NAME = 'FK_EVENT_REFERENCE_RESOURCE')
ALTER TABLE APM.EVENT DROP CONSTRAINT FK_EVENT_REFERENCE_RESOURCE
GO

IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
WHERE
CONSTRAINT_SCHEMA = 'APM' AND CONSTRAINT_NAME = 'FK_EVENT_USERS')
ALTER TABLE APM.EVENT DROP CONSTRAINT FK_EVENT_USERS
GO

IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
WHERE
CONSTRAINT_SCHEMA = 'APM' AND CONSTRAINT_NAME = 'FK_EXCEPTIO_FK_EXCEPT_EVENT')
ALTER TABLE APM.EXCEPTIONNODE DROP CONSTRAINT FK_EXCEPTIO_FK_EXCEPT_EVENT
GO

IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
WHERE
CONSTRAINT_SCHEMA = 'APM' AND CONSTRAINT_NAME = 'FK_EXCEPTIO_REFERENCE_RESOURCE')
ALTER TABLE APM.EXCEPTIONNODE DROP CONSTRAINT FK_EXCEPTIO_REFERENCE_RESOURCE
GO

IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
WHERE
CONSTRAINT_SCHEMA = 'APM' AND CONSTRAINT_NAME = 'FK_MEMBERAP_FK_APPLIC_APPLICAT')
ALTER TABLE APM.MEMBERAPPLICATION DROP CONSTRAINT FK_MEMBERAP_FK_APPLIC_APPLICAT
GO

IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
WHERE
CONSTRAINT_SCHEMA = 'APM' AND CONSTRAINT_NAME = 'FK_MEMBERAP_FK_USER_MEMBER')
ALTER TABLE APM.MEMBERAPPLICATION DROP CONSTRAINT FK_MEMBERAP_FK_USER_MEMBER
GO

IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
WHERE
CONSTRAINT_SCHEMA = 'APM' AND CONSTRAINT_NAME = 'FK_PERFDAYLY_TYPE')
ALTER TABLE APM.PERFDAILY DROP CONSTRAINT FK_PERFDAYLY_TYPE
GO

IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
WHERE
CONSTRAINT_SCHEMA = 'APM' AND CONSTRAINT_NAME = 'FK_PERFDAYLY_MACHINE')
ALTER TABLE APM.PERFDAILY DROP CONSTRAINT FK_PERFDAYLY_MACHINE
GO

IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
WHERE
CONSTRAINT_SCHEMA = 'APM' AND CONSTRAINT_NAME = 'FK_PERFDAYLY_SOURCE')
ALTER TABLE APM.PERFDAILY DROP CONSTRAINT FK_PERFDAYLY_SOURCE
GO

IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
WHERE
CONSTRAINT_SCHEMA = 'APM' AND CONSTRAINT_NAME = 'FK_PERFDAIL_REFERENCE_PCPROCES')
ALTER TABLE APM.PERFDAILY DROP CONSTRAINT FK_PERFDAIL_REFERENCE_PCPROCES
GO

IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
WHERE
CONSTRAINT_SCHEMA = 'APM' AND CONSTRAINT_NAME = 'FK_PERFHOURLY_PCTYPE')
ALTER TABLE APM.PERFHOURLY DROP CONSTRAINT FK_PERFHOURLY_PCTYPE
GO

IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
WHERE
CONSTRAINT_SCHEMA = 'APM' AND CONSTRAINT_NAME = 'FK_PERFHOURLY_MACHINE')
ALTER TABLE APM.PERFHOURLY DROP CONSTRAINT FK_PERFHOURLY_MACHINE
GO

IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
WHERE
CONSTRAINT_SCHEMA = 'APM' AND CONSTRAINT_NAME = 'FK_PERFHOURLY_SOURCE')
ALTER TABLE APM.PERFHOURLY DROP CONSTRAINT FK_PERFHOURLY_SOURCE
GO

IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
WHERE
CONSTRAINT_SCHEMA = 'APM' AND CONSTRAINT_NAME = 'FK_PERFHOUR_REFERENCE_PCPROCES')
ALTER TABLE APM.PERFHOURLY DROP CONSTRAINT FK_PERFHOUR_REFERENCE_PCPROCES
GO

IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
WHERE
CONSTRAINT_SCHEMA = 'APM' AND CONSTRAINT_NAME = 'FK_PERFORMANCENODE_EVENT')
ALTER TABLE APM.PERFORMANCENODE DROP CONSTRAINT FK_PERFORMANCENODE_EVENT
GO

IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
WHERE
CONSTRAINT_SCHEMA = 'APM' AND CONSTRAINT_NAME = 'FK_PERFORMA_REFERENCE_RESOURCEGROUP')
ALTER TABLE APM.PERFORMANCENODE DROP CONSTRAINT FK_PERFORMA_REFERENCE_RESOURCEGROUP
GO

IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
WHERE
CONSTRAINT_SCHEMA = 'APM' AND CONSTRAINT_NAME = 'FK_PERFORMA_REFERENCE_RESOURCE')
ALTER TABLE APM.PERFORMANCENODE DROP CONSTRAINT FK_PERFORMA_REFERENCE_RESOURCE
GO

IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
WHERE
CONSTRAINT_SCHEMA = 'APM' AND CONSTRAINT_NAME = 'FK_RESOURCE_REFERENCE_RESOURCE')
ALTER TABLE APM.RESOURCE DROP CONSTRAINT FK_RESOURCE_REFERENCE_RESOURCE
GO

IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
WHERE
CONSTRAINT_SCHEMA = 'APM' AND CONSTRAINT_NAME = 'FK_RESOURCE_REFERENCE_SOURCE')
ALTER TABLE APM.RESOURCE DROP CONSTRAINT FK_RESOURCE_REFERENCE_SOURCE
GO

IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
WHERE
CONSTRAINT_SCHEMA = 'APM' AND CONSTRAINT_NAME = 'FK_RESOURCE_REFERENCE_RESOURCENODE')
ALTER TABLE APM.RESOURCEGROUPNODE DROP CONSTRAINT FK_RESOURCE_REFERENCE_RESOURCENODE
GO

IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
WHERE
CONSTRAINT_SCHEMA = 'APM' AND CONSTRAINT_NAME = 'FK_RESOURCE_REFERENCE_EVENT')
ALTER TABLE APM.RESOURCEGROUPNODE DROP CONSTRAINT FK_RESOURCE_REFERENCE_EVENT
GO

IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
WHERE
CONSTRAINT_SCHEMA = 'APM' AND CONSTRAINT_NAME = 'FK_TASKS_TaskMode')
ALTER TABLE APM.TASKS DROP CONSTRAINT FK_TASKS_TaskMode
GO

IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
WHERE
CONSTRAINT_SCHEMA = 'APM' AND CONSTRAINT_NAME = 'FK_TASKS_REFERENCE_SEVIEWER')
ALTER TABLE APM.TASKS DROP CONSTRAINT FK_TASKS_REFERENCE_SEVIEWER
GO

IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
WHERE
CONSTRAINT_SCHEMA = 'APM' AND CONSTRAINT_NAME = 'FK_PMSERVEREVENTTRACE_PMTRACE')
ALTER TABLE APM.PMSERVEREVENTTRACE DROP CONSTRAINT FK_PMSERVEREVENTTRACE_PMTRACE
GO

IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
WHERE
CONSTRAINT_SCHEMA = 'APM' AND CONSTRAINT_NAME = 'FK_PMSERVEREVENTTRACE_PMEVENT')
ALTER TABLE APM.PMSERVEREVENTTRACE DROP CONSTRAINT FK_PMSERVEREVENTTRACE_PMEVENT
GO

IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
WHERE
CONSTRAINT_SCHEMA = 'APM' AND CONSTRAINT_NAME = 'FK_PMCLIENTEVENTTRACE_PMTRACE')
ALTER TABLE APM.PMCLIENTEVENTTRACE DROP CONSTRAINT FK_PMCLIENTEVENTTRACE_PMTRACE
GO

IF EXISTS(SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
WHERE
CONSTRAINT_SCHEMA = 'APM' AND CONSTRAINT_NAME = 'FK_PMCLIENTEVENTTRACE_PMEVENT')
ALTER TABLE APM.PMCLIENTEVENTTRACE DROP CONSTRAINT FK_PMCLIENTEVENTTRACE_PMEVENT
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.PMTRACE'), 'IsTable') IS NOT NULL) BEGIN
DROP TABLE APM.PMTRACE
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.PMSERVEREVENTTRACE'), 'IsTable') IS NOT NULL) BEGIN
DROP TABLE APM.PMSERVEREVENTTRACE
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.PMCLIENTEVENTTRACE'), 'IsTable') IS NOT NULL) BEGIN
DROP TABLE APM.PMCLIENTEVENTTRACE
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.PMENTITYMAPPING'), 'IsTable') IS NOT NULL) BEGIN
DROP TABLE APM.PMENTITYMAPPING
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.PMEVENTSTATUS'), 'IsTable') IS NOT NULL) BEGIN
DROP TABLE APM.PMEVENTSTATUS
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.HourlyTable'), 'IsTable') IS NOT NULL)
BEGIN
DROP TABLE APM.HourlyTable
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.AGGREGATIONTYPE'), 'IsTable') IS NOT NULL)
BEGIN
DROP TABLE APM.AGGREGATIONTYPE
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.APPLICATION'), 'IsTable') IS NOT NULL)
BEGIN
DROP TABLE APM.APPLICATION
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.APPLICATIONSOURCEMACHINE'), 'IsTable') IS NOT NULL)
BEGIN
DROP TABLE APM.APPLICATIONSOURCEMACHINE
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.ASPECT'), 'IsTable') IS NOT NULL)
BEGIN
DROP TABLE APM.ASPECT
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.CONFIG'), 'IsTable') IS NOT NULL)
BEGIN
DROP TABLE APM.CONFIG
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.CSAJAX'), 'IsTable') IS NOT NULL)
BEGIN
DROP TABLE APM.CSAJAX
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.CSASYNCAJAX'), 'IsTable') IS NOT NULL)
BEGIN
DROP TABLE APM.CSASYNCAJAX
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.CSEVENT'), 'IsTable') IS NOT NULL)
BEGIN
DROP TABLE APM.CSEVENT
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.CSEVENTGROUP'), 'IsTable') IS NOT NULL)
BEGIN
DROP TABLE APM.CSEVENTGROUP
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.CSEXEVENT'), 'IsTable') IS NOT NULL)
BEGIN
DROP TABLE APM.CSEXEVENT
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.CSHEAVIESTRESOURCE'), 'IsTable') IS NOT NULL)
BEGIN
DROP TABLE APM.CSHEAVIESTRESOURCE
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.CSJSCRIPTEVENT'), 'IsTable') IS NOT NULL)
BEGIN
DROP TABLE APM.CSJSCRIPTEVENT
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.CSPAGEEVENT'), 'IsTable') IS NOT NULL)
BEGIN
DROP TABLE APM.CSPAGEEVENT
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.CSPERIPHERAL'), 'IsTable') IS NOT NULL)
BEGIN
DROP TABLE APM.CSPERIPHERAL
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.CSPERIPHERALDETAIL'), 'IsTable') IS NOT NULL)
BEGIN
DROP TABLE APM.CSPERIPHERALDETAIL
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.DATASET'), 'IsTable') IS NOT NULL)
BEGIN
DROP TABLE APM.DATASET
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.DATASETAGGREGATIONHISTORY'), 'IsTable') IS NOT NULL)
BEGIN
DROP TABLE APM.DATASETAGGREGATIONHISTORY
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.EVENT'), 'IsTable') IS NOT NULL)
BEGIN
DROP TABLE APM.EVENT
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.EVENTGROUP'), 'IsTable') IS NOT NULL)
BEGIN
DROP TABLE APM.EVENTGROUP
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.EXCEPTIONNODE'), 'IsTable') IS NOT NULL)
BEGIN
DROP TABLE APM.EXCEPTIONNODE
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.IP'), 'IsTable') IS NOT NULL)
BEGIN
DROP TABLE APM.IP
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.MACHINE'), 'IsTable') IS NOT NULL)
BEGIN
DROP TABLE APM.MACHINE
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.MEMBER'), 'IsTable') IS NOT NULL)
BEGIN
DROP TABLE APM.MEMBER
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.MEMBERAPPLICATION'), 'IsTable') IS NOT NULL)
BEGIN
DROP TABLE APM.MEMBERAPPLICATION
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.MESSAGES'), 'IsTable') IS NOT NULL)
BEGIN
DROP TABLE APM.MESSAGES
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.OPERATION'), 'IsTable') IS NOT NULL)
BEGIN
DROP TABLE APM.OPERATION
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.PCDESCRIPTION'), 'IsTable') IS NOT NULL)
BEGIN
DROP TABLE APM.PCDESCRIPTION
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.PCPROCESS'), 'IsTable') IS NOT NULL)
BEGIN
drop table APM.PCPROCESS
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.PCTYPE'), 'IsTable') IS NOT NULL)
BEGIN
DROP TABLE APM.PCTYPE
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.PERFDAILY'), 'IsTable') IS NOT NULL)
BEGIN
DROP TABLE APM.PERFDAILY
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.PERFHOURLY'), 'IsTable') IS NOT NULL)
BEGIN
DROP TABLE APM.PERFHOURLY
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.PERFORMANCENODE'), 'IsTable') IS NOT NULL)
BEGIN
DROP TABLE APM.PERFORMANCENODE
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.RELATIVEDATES'), 'IsTable') IS NOT NULL)
BEGIN
DROP TABLE APM.RELATIVEDATES
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.RESOURCE'), 'IsTable') IS NOT NULL)
BEGIN
DROP TABLE APM.RESOURCE
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.RESOURCEGROUP'), 'IsTable') IS NOT NULL)
BEGIN
DROP TABLE APM.RESOURCEGROUP
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.RESOURCEGROUPNODE'), 'IsTable') IS NOT NULL)
BEGIN
DROP TABLE APM.RESOURCEGROUPNODE
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.SEVIEWERDB'), 'IsTable') IS NOT NULL)
BEGIN
DROP TABLE APM.SEVIEWERDB
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.SOURCE'), 'IsTable') IS NOT NULL)
BEGIN
DROP TABLE APM.SOURCE
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.TASKS'), 'IsTable') IS NOT NULL)
BEGIN
DROP TABLE APM.TASKS
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.TIMEZONE'), 'IsTable') IS NOT NULL)
BEGIN
DROP TABLE APM.TIMEZONE
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.USERS'), 'IsTable') IS NOT NULL)
BEGIN
DROP TABLE APM.USERS
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.EVENTDETAIL'), 'IsTable') IS NOT NULL)
BEGIN
DROP TABLE APM.EVENTDETAIL
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.CSEVENTDETAIL'), 'IsTable') IS NOT NULL)
BEGIN
DROP TABLE APM.CSEVENTDETAIL
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.V_APPLICATIONSOURCEMACHINE'), 'IsView') IS Not NULL)
BEGIN
EXECUTE('DROP VIEW APM.V_APPLICATIONSOURCEMACHINE')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.V_EVENTWINDOW'), 'IsView') IS Not NULL)
BEGIN
EXECUTE('DROP VIEW APM.V_EVENTWINDOW')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.FN_ADMINUSER'), 'IsScalarFunction') IS NOT NULL)
BEGIN
EXECUTE('DROP FUNCTION APM.FN_ADMINUSER')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.FN_ISSECURE'), 'IsScalarFunction') IS NOT NULL)
BEGIN
EXECUTE('DROP FUNCTION APM.FN_ISSECURE')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.DATASETAGGREGATE'), 'IsProcedure') IS NOT NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.DATASETAGGREGATE')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.PCOUNTERAGGREGATE'), 'IsProcedure') IS NOT NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.PCOUNTERAGGREGATE')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.RUNDAILYAGGREGATEOPERATION'), 'IsProcedure') IS NOT NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.RUNDAILYAGGREGATEOPERATION')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.HourlyTableInit'), 'IsProcedure') IS NOT NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.HourlyTableInit')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.DISABLE_FOREIGN_KEYS'), 'IsProcedure') IS NOT NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.DISABLE_FOREIGN_KEYS')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.SHOWMESSAGE'), 'IsProcedure') IS NOT NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.SHOWMESSAGE')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.FILLGROUPS'), 'IsProcedure') IS NOT NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.FILLGROUPS')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.FillResourceGroupNodes'), 'IsProcedure') IS NOT NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.FillResourceGroupNodes')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.FILLRESOURCES'), 'IsProcedure') IS NOT NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.FILLRESOURCES')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.UpdateEventsByInternalResource'), 'IsProcedure') IS NOT NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.UpdateEventsByInternalResource')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.INSERTINTERNALRESOURCE'), 'IsProcedure') IS NOT NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.INSERTINTERNALRESOURCE')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.FILLINTERNALRESOURCES'), 'IsProcedure') IS NOT NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.FILLINTERNALRESOURCES')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.GetResource'), 'IsScalarFunction') IS NOT NULL)
BEGIN
EXECUTE('DROP FUNCTION APM.GetResource')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.GetResourceType'), 'IsScalarFunction') IS NOT NULL)
BEGIN
EXECUTE('DROP FUNCTION APM.GetResourceType')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.ComputerResourceUtilization'), 'IsProcedure') IS NOT NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.ComputerResourceUtilization')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.fn_nums'), 'IsTableFunction') IS NOT NULL)
BEGIN
EXECUTE('DROP FUNCTION APM.fn_nums')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.RemoveProcessIdFromName'), 'IsScalarFunction') IS NOT NULL)
BEGIN
EXECUTE('DROP FUNCTION APM.RemoveProcessIdFromName')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.ComputerResourceUtilizationBySource'), 'IsProcedure') IS NOT NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.ComputerResourceUtilizationBySource')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.GetQueryDateCount'), 'IsScalarFunction') IS NOT NULL)
BEGIN
EXECUTE('DROP FUNCTION APM.GetQueryDateCount')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.GetDatePart'), 'IsScalarFunction') IS NOT NULL)
BEGIN
EXECUTE('DROP FUNCTION APM.GetDatePart')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.DATES'), 'IsTable') IS NOT NULL)
BEGIN
DROP TABLE APM.DATES
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.ApplicationResourceUtilization'), 'IsProcedure') IS NOT NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.ApplicationResourceUtilization')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.GetTop10MostFrequentFailureReport'), 'IsProcedure') IS NOT NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.GetTop10MostFrequentFailureReport')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.GetTop10MostFrequentPerformanceReport'), 'IsProcedure') IS NOT NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.GetTop10MostFrequentPerformanceReport')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.GetTOP10NewExceptionProblems'), 'IsProcedure') IS NOT NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.GetTOP10NewExceptionProblems')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.GetTOP10NewPerformanceProblems'), 'IsProcedure') IS NOT NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.GetTOP10NewPerformanceProblems')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.GetAbsDateByRelative'), 'IsScalarFunction') IS NOT NULL)
BEGIN
EXECUTE('DROP FUNCTION APM.GetAbsDateByRelative')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.GetMultiParameters'), 'IsTableFunction') IS NOT NULL)
BEGIN
DROP FUNCTION APM.GetMultiParameters
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.ResourceUtilizationTrend'), 'IsProcedure') IS NOT NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.ResourceUtilizationTrend')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.Source_sync'), 'IsProcedure') IS NOT NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.Source_sync')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.Machine_sync'), 'IsProcedure') IS NOT NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.Machine_sync')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.PCType_sync'), 'IsProcedure') IS NOT NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.PCType_sync')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.Aspect_sync'), 'IsProcedure') IS NOT NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.Aspect_sync')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.EventGroup_sync'), 'IsProcedure') IS NOT NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.EventGroup_sync')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.PCProcess_sync'), 'IsProcedure') IS NOT NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.PCProcess_sync')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.PCDescription_sync'), 'IsProcedure') IS NOT NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.PCDescription_sync')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.PMCREATEEVENTTRACES'), 'IsProcedure') IS NOT NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.PMCREATEEVENTTRACES')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.ServerEvent_sync'), 'IsProcedure') IS NOT NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.ServerEvent_sync')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.PerformanceNode_sync'), 'IsProcedure') IS not NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.PerformanceNode_sync')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.ExceptionNode_sync'), 'IsProcedure') IS not NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.ExceptionNode_sync')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.PerfHourly_sync'), 'IsProcedure') IS not NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.PerfHourly_sync')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.CheckDatabaseId'), 'IsProcedure') IS not NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.CheckDatabaseId')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.CheckAndCreateDatabaseId'), 'IsProcedure') IS not NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.CheckAndCreateDatabaseId')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.Config_sync'), 'IsProcedure') IS not NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.Config_sync')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.PageEvent_sync'), 'IsProcedure') IS not NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.PageEvent_sync')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.AjaxCall_sync'), 'IsProcedure') IS not NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.AjaxCall_sync')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.JScriptEvent_sync'), 'IsProcedure') IS not NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.JScriptEvent_sync')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.ClientEvent_sync'), 'IsProcedure') IS not NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.ClientEvent_sync')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.Event_sync'), 'IsProcedure') IS not NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.Event_sync')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.CheckConfiguration'), 'IsProcedure') IS not NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.CheckConfiguration')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.CreateOrUpdateTaskStatus'), 'IsProcedure') IS not NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.CreateOrUpdateTaskStatus')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.SelectAbsDateORRelative'), 'IsScalarFunction') IS NOT NULL)
BEGIN
EXECUTE('DROP FUNCTION APM.SelectAbsDateORRelative')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.EventDetail_sync'), 'IsProcedure') IS not NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.EventDetail_sync')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.GetDependentComputersList'), 'IsProcedure') IS not NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.GetDependentComputersList')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.ApplicationStatusSummaryStatistics'), 'IsProcedure') IS not NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.ApplicationStatusSummaryStatistics')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.ApplicationStatusDrillthrough'), 'IsProcedure') IS not NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.ApplicationStatusDrillthrough')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.Application_sync'), 'IsProcedure') IS not NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.Application_sync')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.ApplicationSourceMachine_sync'), 'IsProcedure') IS not NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.ApplicationSourceMachine_sync')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.SummaryQualityAnalysis'), 'IsProcedure') IS not NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.SummaryQualityAnalysis')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.SummarySizeAnalysisReport'), 'IsProcedure') IS not NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.SummarySizeAnalysisReport')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.SummarySizeAnalysisTopAJAXSubReport'), 'IsProcedure') IS not NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.SummarySizeAnalysisTopAJAXSubReport')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.SummarySizeAnalysisTopPagesSubReport'), 'IsProcedure') IS not NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.SummarySizeAnalysisTopPagesSubReport')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.TopUserPerformanceIssues'), 'IsProcedure') IS not NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.TopUserPerformanceIssues')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.TopUserExceptionIssues'), 'IsProcedure') IS not NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.TopUserExceptionIssues')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.SummaryPerformanceAnalysisReport'), 'IsProcedure') IS not NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.SummaryPerformanceAnalysisReport')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.SummaryPerformanceAnalysisReportMaxScale'), 'IsProcedure') IS not NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.SummaryPerformanceAnalysisReportMaxScale')
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.LoadTimeAnalysisBasedOnSubNet'), 'IsProcedure') IS not NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.LoadTimeAnalysisBasedOnSubNet')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.LoadTimeAnalysisBasedOnSubNetMaxScale'), 'IsProcedure') IS not NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.LoadTimeAnalysisBasedOnSubNetMaxScale')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.LoadTimeAnalysisBasedOnSubNetTopJSAndAJAXCalls'), 'IsProcedure') IS not NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.LoadTimeAnalysisBasedOnSubNetTopJSAndAJAXCalls')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.LoadTimeAnalysisBasedOnSubNetTopPages'), 'IsProcedure') IS not NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.LoadTimeAnalysisBasedOnSubNetTopPages')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.ClientLatencyDistributionBySources'), 'IsProcedure') IS not NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.ClientLatencyDistributionBySources')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.ClientLatencyDistributionSubReport'), 'IsProcedure') IS not NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.ClientLatencyDistributionSubReport')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.ApplicationAnalysisJScriptWithAjaxCalls'), 'IsProcedure') IS not NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.ApplicationAnalysisJScriptWithAjaxCalls')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.ApplicationAnalysisTopPages'), 'IsProcedure') IS not NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.ApplicationAnalysisTopPages')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.SummaryPerformanceTopPages'), 'IsProcedure') IS not NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.SummaryPerformanceTopPages')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.ApplicationAnalysisExceptionEvents'), 'IsProcedure') IS not NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.ApplicationAnalysisExceptionEvents')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.ApplicationAnalysisOverallStatistics'), 'IsProcedure') IS not NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.ApplicationAnalysisOverallStatistics')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.SummaryPerformanceAnalysisReportTopJS'), 'IsProcedure') IS not NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.SummaryPerformanceAnalysisReportTopJS')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.ApplicationActivityBreakdownByMonthDate'), 'IsProcedure') IS not NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.ApplicationActivityBreakdownByMonthDate')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.ApplicationActivityBreakdown'), 'IsProcedure') IS not NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.ApplicationActivityBreakdown')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.SummaryUserAnalysisCSM'), 'IsProcedure') IS not NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.SummaryUserAnalysisCSM')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.PCType_ConfigSync'), 'IsProcedure') IS not NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.PCType_ConfigSync')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.DeleteEventsOrEventGroups'), 'IsProcedure') IS not NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.DeleteEventsOrEventGroups')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.ExtractEventGroomingRows'), 'IsProcedure') IS not NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.ExtractEventGroomingRows')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.GroomingWorkTables'), 'IsProcedure') IS not NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.GroomingWorkTables')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.GetOldComputersOrSources'), 'IsProcedure') IS not NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.GetOldComputersOrSources')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.CalculateOldComputersOrSources'), 'IsProcedure') IS not NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.CalculateOldComputersOrSources')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.GroomingOldComputersOrSources'), 'IsProcedure') IS not NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.GroomingOldComputersOrSources')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.GetApplicationGroups'), 'IsProcedure') IS not NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.GetApplicationGroups')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.GroomingOldApplicationGroup'), 'IsProcedure') IS not NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.GroomingOldApplicationGroup')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.ApplicationStatusClient'), 'IsProcedure') IS not NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.ApplicationStatusClient')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.ApplicationStatusClientFrequentCSMEvents'), 'IsProcedure') IS not NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.ApplicationStatusClientFrequentCSMEvents')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.ApplicationStatusClientFrequentFailure'), 'IsProcedure') IS not NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.ApplicationStatusClientFrequentFailure')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.ApplicationStatusClientFrequentPerformance'), 'IsProcedure') IS not NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.ApplicationStatusClientFrequentPerformance')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.ApplicationStatusClientNewCSMEvents'), 'IsProcedure') IS not NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.ApplicationStatusClientNewCSMEvents')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.ApplicationStatusClientNewFailure'), 'IsProcedure') IS not NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.ApplicationStatusClientNewFailure')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.ApplicationStatusClientNewPerformance'), 'IsProcedure') IS not NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.ApplicationStatusClientNewPerformance')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.V_PM_EMPTY'), 'IsView') IS NOT NULL) BEGIN
EXECUTE('DROP VIEW APM.V_PM_EMPTY')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.V_PM_CSEVENTSTATUS'), 'IsView') IS NOT NULL) BEGIN
EXECUTE('DROP VIEW APM.V_PM_CSEVENTSTATUS')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.V_PM_HEAVIESTNODE'), 'IsView') IS NOT NULL) BEGIN
EXECUTE('DROP VIEW APM.V_PM_HEAVIESTNODE')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.V_PM_CSHEAVIESTNODE'), 'IsView') IS NOT NULL) BEGIN
EXECUTE('DROP VIEW APM.V_PM_CSHEAVIESTNODE')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.V_PM_EVENT'), 'IsView') IS NOT NULL) BEGIN
EXECUTE('DROP VIEW APM.V_PM_EVENT')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.V_PM_EVENTDETAIL'), 'IsView') IS NOT NULL) BEGIN
EXECUTE('DROP VIEW APM.V_PM_EVENTDETAIL')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.V_PM_CSEVENTDETAIL'), 'IsView') IS NOT NULL) BEGIN
EXECUTE('DROP VIEW APM.V_PM_CSEVENTDETAIL')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.V_PM_RESOURCE'), 'IsView') IS NOT NULL) BEGIN
EXECUTE('DROP VIEW APM.V_PM_RESOURCE')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.V_PM_CSEVENT'), 'IsView') IS NOT NULL) BEGIN
EXECUTE('DROP VIEW APM.V_PM_CSEVENT')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.PMACTIONQUERY'), 'IsProcedure') IS not NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.PMACTIONQUERY')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.PMEXPRESSIONQUERY'), 'IsProcedure') IS not NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.PMEXPRESSIONQUERY')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.PMIntersectExpressionQuery'), 'IsProcedure') IS not NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.PMIntersectExpressionQuery')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.PMQueryForRule'), 'IsProcedure') IS not NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.PMQueryForRule')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.PMApplyActionsToDb'), 'IsProcedure') IS not NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.PMApplyActionsToDb')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.PMApplyToDbForEventType'), 'IsProcedure') IS not NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.PMApplyToDbForEventType')
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.PMApplyToDb'), 'IsProcedure') IS not NULL)
BEGIN
EXECUTE ('DROP PROCEDURE APM.PMApplyToDb')
END
GO

</Uninstall>
<Upgrade>IF (OBJECTPROPERTY(OBJECT_ID('APM.PMTRACE'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.PMTRACE (
PMTRACEID INT IDENTITY(1,1) NOT NULL,
UTCDATE DATETIME NOT NULL,
DATA NVARCHAR(MAX) NULL,
PMSTATUS tinyint NULL
CONSTRAINT PK_PMTRACE PRIMARY KEY (PMTRACEID)
)
END
GO

IF NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'PMTRACE' AND TABLE_SCHEMA = N'apm' AND COLUMN_NAME = 'UTCDATE' AND COLUMN_DEFAULT IS NOT NULL)
BEGIN
ALTER TABLE APM.PMTRACE ADD CONSTRAINT DF_PMTRACE_UTCDATE DEFAULT GETUTCDATE() FOR UTCDATE;
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.PMSERVEREVENTTRACE'), 'IsTable') IS NULL)
BEGIN
/* server event trace table */
CREATE TABLE APM.PMSERVEREVENTTRACE (
EVENTID BIGINT NOT NULL,
PMTRACEID INT NOT NULL
)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PMSERVEREVENTTRACE]') AND name = N'IDX_EVENTID'
)
BEGIN
CREATE INDEX IDX_EVENTID ON APM.PMSERVEREVENTTRACE
(
EVENTID
)
INCLUDE(PMTRACEID)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PMSERVEREVENTTRACE]') AND name = N'IX_PMSERVEREVENTTRACE_PMTRACEID'
)
BEGIN
CREATE INDEX IX_PMSERVEREVENTTRACE_PMTRACEID ON APM.PMSERVEREVENTTRACE
(PMTRACEID)
END
GO

EXEC DomainTableRegisterIndexOptimization
@TableName = 'PMSERVEREVENTTRACE'
,@SchemaName = 'APM'
,@DatasetId = '$Config/DatasetId$'
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.ADT_PMSERVEREVENTTRACE'), 'IsTrigger') IS NULL)
BEGIN
exec(
'CREATE TRIGGER APM.ADT_PMSERVEREVENTTRACE ON APM.PMSERVEREVENTTRACE AFTER DELETE
AS
BEGIN
RETURN;
END')
END
GO

ALTER TRIGGER APM.ADT_PMSERVEREVENTTRACE ON APM.PMSERVEREVENTTRACE AFTER DELETE
AS
BEGIN
SET NOCOUNT ON
DELETE a FROM
APM.PMTRACE a JOIN deleted b ON a.PMTRACEID=b.PMTRACEID
WHERE NOT EXISTS (SELECT 1 FROM APM.PMSERVEREVENTTRACE WHERE PMTRACEID=a.PMTRACEID)
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.PMCLIENTEVENTTRACE'), 'IsTable') IS NULL)
BEGIN
/* client event trace table */
CREATE TABLE APM.PMCLIENTEVENTTRACE (
CSEVENTID INT NOT NULL,
PMTRACEID INT NOT NULL
)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PMCLIENTEVENTTRACE]') AND name = N'IDX_EVENTID'
)
BEGIN
CREATE INDEX IDX_EVENTID ON APM.PMCLIENTEVENTTRACE
(CSEVENTID)
INCLUDE(PMTRACEID)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PMCLIENTEVENTTRACE]') AND name = N'IX_PMCLIENTEVENTTRACE_PMTRACEID'
)
BEGIN
CREATE INDEX IX_PMCLIENTEVENTTRACE_PMTRACEID ON APM.PMCLIENTEVENTTRACE
(PMTRACEID)
END
GO

EXEC DomainTableRegisterIndexOptimization
@TableName = 'PMCLIENTEVENTTRACE'
,@SchemaName = 'APM'
,@DatasetId = '$Config/DatasetId$'
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.ADT_PMCLIENTEVENTTRACE'), 'IsTrigger') IS NULL)
BEGIN
EXEC('
CREATE TRIGGER APM.ADT_PMCLIENTEVENTTRACE ON APM.PMCLIENTEVENTTRACE
AFTER DELETE
AS
BEGIN
RETURN;
END')
END
GO

ALTER TRIGGER APM.ADT_PMCLIENTEVENTTRACE ON APM.PMCLIENTEVENTTRACE
AFTER DELETE
AS
BEGIN
SET NOCOUNT ON

DELETE a FROM
APM.PMTRACE a JOIN deleted b ON a.PMTRACEID=b.PMTRACEID
WHERE NOT EXISTS (SELECT 1 FROM APM.PMCLIENTEVENTTRACE WHERE PMTRACEID=a.PMTRACEID)
END
go

IF (OBJECTPROPERTY(OBJECT_ID('APM.PMENTITYMAPPING'), 'IsTable') IS NULL)
BEGIN
/*==============================================================*/
/* Table: PMENTITYMAPPING */
/*==============================================================*/
CREATE TABLE APM.PMENTITYMAPPING (
PMENTITYMAPPINGID INT IDENTITY,
ALIAS NVARCHAR(50) NOT NULL,
ENTITY NVARCHAR(50) NOT NULL,
FIELD NVARCHAR(50) NULL,
FIELDTYPE NVARCHAR(50) NULL,
ISPROCEDURE BIT NOT NULL,
ISCLIENT BIT NOT NULL,
CONSTRAINT PK_PMENTITYMAPPING PRIMARY KEY (PMENTITYMAPPINGID)
)

------------------ SERVER EVENT MAPING ------------------------
INSERT APM.PMENTITYMAPPING
(
ALIAS,
ENTITY,
FIELD,
FIELDTYPE ,
ISPROCEDURE,
ISCLIENT
)
SELECT N'EVENT.EVENTCLASSTYPE',N'V_PM_EVENT',N'EVENTCLASSTYPE',N'nvarchar(50)',0,0
UNION ALL
SELECT N'EVENT.SOURCE',N'V_PM_EVENT',N'SOURCE',N'nvarchar(255)',0,0
UNION ALL
SELECT N'EVENT.MACHINENAME',N'V_PM_EVENT',N'MACHINENAME',N'nvarchar(255)',0,0
UNION ALL
SELECT N'EVENT.ROOTNODENAME',N'V_PM_EVENT',N'ROOTNODENAME',N'nvarchar(255)',0,0
UNION ALL
SELECT N'EVENT.DESCRIPTION',N'V_PM_EVENT',N'DESCRIPTION',N'nvarchar(255)',0,0
UNION ALL
SELECT N'EVENT.USERNAME',N'V_PM_EVENT',N'USERNAME',N'nvarchar(255)',0,0
UNION ALL
SELECT N'EVENT.EXCEPTIONCLASS',N'V_PM_EVENT',N'EXCEPTIONCLASS',N'nvarchar(255)',0,0
UNION ALL
SELECT N'EVENT.EVENTDURATION',N'V_PM_EVENT',N'EVENTDURATION',N'decimal(35,0)',0,0
UNION ALL
SELECT N'EVENT.EVENTGROUPID',N'V_PM_EVENT',N'SEVIEWEREGID',N'int',0,0
UNION ALL
SELECT N'EVENT.HEAVYLIGHT',N'V_PM_EVENT',N'HEAVYLIGHT',N'int',0,0
UNION ALL
SELECT N'EVENT.ASPECT',N'V_PM_EVENT',N'ASPECT',N'nvarchar(50)',0,0
UNION ALL
SELECT N'EVENT.PMSTATUS',N'EVENT',N'PMSTATUS',N'tinyint',0,0
UNION ALL
SELECT N'EVENT.HEAVIESTEXTERNALRESOURCE',N'V_PM_RESOURCE',N'RESOURCEMETHOD',N'nvarchar(255)',0,0
UNION ALL
SELECT N'EVENT.COMPONENT',N'V_PM_EVENTDETAIL',N'VALUE',N'COMPONENT',0,0
UNION ALL
SELECT N'EVENT.EVENTID',N'EVENT',N'EVENTID',N'int',0,0
UNION ALL
SELECT N'EVENT.CATEGORY',N'V_PM_EVENT',N'CATEGORY',N'nvarchar(50)',0,0
UNION ALL
SELECT N'EVENT.HEAVIESTNODE',N'V_PM_HEAVIESTNODE',N'VAL',N'nvarchar(255)',0,0
UNION ALL
SELECT N'EVENT.ROOTFUNCTION',N'V_PM_EVENTDETAIL',N'VALUE',N'ROOTFUNCTION',0,0
UNION ALL
SELECT N'EVENT.SLOWCALLDURATION',N'V_PM_HEAVIESTNODE',N'SELFDURATION',N'decimal(35,0)',0,0

------------------ CLIENT EVENT MAPING ------------------------
INSERT APM.PMENTITYMAPPING
(
ALIAS,
ENTITY,
FIELD,
FIELDTYPE ,
ISPROCEDURE,
ISCLIENT
)
SELECT N'EVENT.EVENTCLASSTYPE',N'V_PM_CSEVENT',N'EVENTCLASSTYPE',N'nvarchar(50)',0,1
UNION ALL
SELECT N'EVENT.SOURCE',N'V_PM_CSEVENT',N'SOURCE',N'nvarchar(255)',0,1
UNION ALL
SELECT N'EVENT.MACHINENAME',N'V_PM_CSEVENT',N'MACHINENAME',N'nvarchar(255)',0,1
UNION ALL
SELECT N'EVENT.ROOTNODENAME',N'V_PM_CSEVENTDETAIL',N'VALUE',N'ROOTNODENAME',0,1
UNION ALL
SELECT N'EVENT.DESCRIPTION',N'V_PM_CSEVENT',N'DESCRIPTION',N'nvarchar(255)',0,1
UNION ALL
SELECT N'EVENT.USERNAME',N'V_PM_CSEVENT',N'USERNAME',N'nvarchar(255)',0,1
UNION ALL
SELECT N'EVENT.EXCEPTIONCLASS',N'V_PM_CSEVENT',N'EXCEPTIONCLASS',N'nvarchar(255)',0,1
UNION ALL
SELECT N'EVENT.EVENTDURATION',N'V_PM_CSEVENT',N'EVENTDURATION',N'decimal(35,0)',0,1
UNION ALL
SELECT N'EVENT.EVENTGROUPID',N'V_PM_CSEVENT',N'SEVIEWEREGID',N'int',0,1
UNION ALL
SELECT N'EVENT.HEAVYLIGHT',N'V_PM_CSEVENT',N'HEAVYLIGHT',N'int',0,1
UNION ALL
SELECT N'EVENT.ASPECT',N'V_PM_CSEVENT',N'ASPECT',N'nvarchar(50)',0,1
UNION ALL
SELECT N'EVENT.PMSTATUS',N'V_PM_CSEVENTSTATUS',N'PMSTATUS',N'tinyint',0,1
UNION ALL
SELECT N'EVENT.HEAVIESTEXTERNALRESOURCE',N'V_PM_EMPTY',N'VAL',N'nvarchar(255)',0,1
UNION ALL
SELECT N'EVENT.COMPONENT',N'V_PM_CSEVENT',N'COMPONENT',N'nvarchar(50)',0,1
UNION ALL
SELECT N'EVENT.EVENTID',N'V_PM_CSEVENTSTATUS',N'EVENTID',N'int',0,1
UNION ALL
SELECT N'EVENT.CATEGORY',N'V_PM_CSEVENTDETAIL',N'VALUE',N'CATEGORY',0,1
UNION ALL
SELECT N'EVENT.HEAVIESTNODE',N'V_PM_CSHEAVIESTNODE',N'VAL',N'nvarchar(255)',0,1
UNION ALL
SELECT N'EVENT.ROOTFUNCTION',N'V_PM_CSEVENTDETAIL',N'VALUE',N'ROOTFUNCTION',0,1
UNION ALL
SELECT N'EVENT.SLOWCALLDURATION',N'V_PM_CSHEAVIESTNODE',N'SELFDURATION',N'decimal(35,0)',0,1
END
GO

IF NOT EXISTS
(
SELECT * FROM INFORMATION_SCHEMA.table_constraints WHERE TABLE_NAME = N'PMENTITYMAPPING' AND TABLE_SCHEMA = N'apm' AND CONSTRAINT_NAME=N'PMENTITYMAPPING_UNIQUE'
)
BEGIN
ALTER TABLE APM.PMENTITYMAPPING ADD CONSTRAINT PMENTITYMAPPING_UNIQUE
UNIQUE(ALIAS, ISCLIENT)
END
GO

/*==============================================================*/
/* Table: PMEVENTSTATUS */
/*==============================================================*/

IF (OBJECTPROPERTY(OBJECT_ID('APM.PMEVENTSTATUS'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.PMEVENTSTATUS (
PMSTATUSID int not null,
PMSTATUSNAME nvarchar(50) not null,
ISDEFAULT bit not null
)

INSERT INTO [APM].[PMEVENTSTATUS] ([PMSTATUSID], [PMSTATUSNAME], [ISDEFAULT])
SELECT 0, N'New', 1
UNION
SELECT 1, N'Reviewed', 1
UNION
SELECT 2, N'Deleted', 0
UNION
SELECT 3, N'By Design', 0
END
GO

IF NOT EXISTS (
SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'PMEVENTSTATUS' AND TABLE_SCHEMA = N'apm' AND COLUMN_NAME = 'ISDEFAULT' AND COLUMN_DEFAULT IS NOT NULL
)
BEGIN
ALTER TABLE APM.PMEVENTSTATUS ADD CONSTRAINT DF_PMEVENTSTATUS_ISDEFAULT DEFAULT 0 FOR ISDEFAULT
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.HourlyTable'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.HourlyTable (value datetime)
END
GO

/*==============================================================*/
/* Table: AGGREGATIONTYPE */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.AGGREGATIONTYPE'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.AGGREGATIONTYPE (
AGGREGATIONTYPEID int not null,
AGGREGATIONTYPEDEFAULTNAME nvarchar(50) not null,
AGGREGATIONINTERVALDURATIONMINUTES int not null,
AGGREGATIONSTARTDELAYMINUTES int not null,
constraint PK_AGGREGATIONTYPE primary key (AGGREGATIONTYPEID)
)

INSERT INTO APM.AGGREGATIONTYPE (
AGGREGATIONTYPEID,
AGGREGATIONTYPEDEFAULTNAME,
AGGREGATIONINTERVALDURATIONMINUTES,
AGGREGATIONSTARTDELAYMINUTES
)
values(
20,
'Hourly',
60,
5
)

INSERT INTO APM.AGGREGATIONTYPE (
AGGREGATIONTYPEID,
AGGREGATIONTYPEDEFAULTNAME,
AGGREGATIONINTERVALDURATIONMINUTES,
AGGREGATIONSTARTDELAYMINUTES
)
VALUES(
30,
'Daily',
1440,
20
)
END
GO

/*==============================================================*/
/* Table: APPLICATION */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.APPLICATION'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.APPLICATION (
APPLICATIONID int identity,
APPLICATION nvarchar(255) null,
TYPE int not null,
constraint PK_APPLICATION primary key (APPLICATIONID)
)
END
GO

/*==============================================================*/
/* Index: IX_APPLICATION */
/*==============================================================*/
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[APPLICATION]') AND name = N'IX_APPLICATION'
)
BEGIN
create unique index IX_APPLICATION on APM.APPLICATION (
APPLICATION ASC
)
END
GO

/*==============================================================*/
/* Table: APPLICATIONSOURCEMACHINE */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.APPLICATIONSOURCEMACHINE'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.APPLICATIONSOURCEMACHINE (
APPLICATIONSOURCEID int identity,
APPLICATIONID int null,
SOURCEID int null,
MACHINEID int null,
constraint PK_APPLICATIONSOURCEMACHINE primary key (APPLICATIONSOURCEID)
)
END
GO

/*==============================================================*/
/* Index: FK_SOURCE */
/*==============================================================*/
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[APPLICATIONSOURCEMACHINE]') AND name = N'FK_SOURCE'
)
BEGIN
create index FK_SOURCE on APM.APPLICATIONSOURCEMACHINE
(
SOURCEID ASC
)
INCLUDE ( [APPLICATIONID]) WITH (SORT_IN_TEMPDB = ON) ON [PRIMARY]
END
GO

/*==============================================================*/
/* Index: FK_APPLICATION */
/*==============================================================*/
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[APPLICATIONSOURCEMACHINE]') AND name = N'FK_APPLICATION'
)
BEGIN
create index FK_APPLICATION on APM.APPLICATIONSOURCEMACHINE (
APPLICATIONID ASC
)
END
GO

/*==============================================================*/
/* Index: FK_MACHINE */
/*==============================================================*/
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[APPLICATIONSOURCEMACHINE]') AND name = N'FK_MACHINE'
)
BEGIN
create index FK_MACHINE on APM.APPLICATIONSOURCEMACHINE (
MACHINEID ASC
)
INCLUDE ([APPLICATIONID])
END
GO

/*==============================================================*/
/* Table: ASPECT */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.ASPECT'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.ASPECT (
ASPECT nvarchar(50) null,
DESCRIPTION nvarchar(255) null,
ASPECTID int identity,
constraint PK_ASPECT primary key (ASPECTID)
)
END
GO

/*==============================================================*/
/* Index: IX_ASPECT */
/*==============================================================*/
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[ASPECT]') AND name = N'IX_ASPECT'
)
BEGIN
create unique index IX_ASPECT on APM.ASPECT (
ASPECT ASC
)
END
GO

/*==============================================================*/
/* Table: CONFIG */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.CONFIG'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.CONFIG (
CONFIGID int identity,
CONFIGNAME nvarchar(50) not null,
CONFIGVALUE ntext null,
constraint PK_CONFIG primary key (CONFIGID)
)

INSERT INTO APM.CONFIG (configname, configvalue) VALUES ('SECURITYMODE', '0')
INSERT INTO APM.CONFIG (CONFIGNAME, CONFIGVALUE) VALUES ('DATABASE_VERSION', '5.7')
INSERT INTO APM.CONFIG (CONFIGNAME, CONFIGVALUE) VALUES ('DATABASE_NAME', 'Reporting')
INSERT INTO APM.CONFIG (CONFIGNAME, CONFIGVALUE) VALUES ('SCHEMA_VERSION', '1')

/*Lifetime for events with "Deleted" status (hours)*/
INSERT INTO APM.CONFIG (CONFIGNAME, CONFIGVALUE) VALUES (N'PMLifeTimeInHoursForDeletedEvents', '24')

/*Lifetime for events with "By Design" status (hours)*/
INSERT INTO APM.CONFIG (CONFIGNAME, CONFIGVALUE) VALUES (N'PMLifeTimeInHoursForByDesignEvents', '72')
END
GO

/*==============================================================*/
/* Index: IX_CONFIGNAME */
/*==============================================================*/
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CONFIG]') AND name = N'IX_CONFIGNAME'
)
BEGIN
CREATE UNIQUE INDEX IX_CONFIGNAME on APM.CONFIG (
CONFIGNAME ASC
)
END
GO

/*==============================================================*/
/* Table: CSAJAX */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.CSAJAX'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.CSAJAX (
CSAJAXID int identity,
CSEVENTID int not null,
URI nvarchar(255) not null,
NETWORKTIME decimal(35) null,
SERVERTIME decimal(35) null,
TOTALTIME decimal(35) null,
REQUESTSIZE bigint null,
RESPONSESIZE bigint null,
RESPONSETIME decimal(35) null,
SYNCHRONOUS bit not null,
LATENCY bigint null,
UTCDATE datetime null,
SOURCEID int null,
ISHEAVIESTNODE bit not null,
constraint PK_CSAJAX primary key (CSAJAXID)
)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSAJAX]') AND name = N'idx_W_EventURI'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_W_EventURI] ON [APM].[CSAJAX]
(
[CSEVENTID] ASC,
[URI] ASC
)
INCLUDE ( [TOTALTIME],
[SYNCHRONOUS]) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSAJAX]') AND name = N'FK_CSEVENTID'
)
BEGIN
CREATE NONCLUSTERED INDEX [FK_CSEVENTID] ON [APM].[CSAJAX]
(
[CSEVENTID] ASC
) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSAJAX]') AND name = N'idx_EventId'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_EventId] ON [APM].[CSAJAX]
(
[CSEVENTID] ASC
)
INCLUDE ( [TOTALTIME],
[RESPONSESIZE],
[LATENCY],
[SYNCHRONOUS],
[URI],
[NETWORKTIME],
[SERVERTIME],
[REQUESTSIZE]
) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSAJAX]') AND name = N'idx_EventIdTotalTime1'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_EventIdTotalTime1] ON APM.CSAJAX
(
[CSEVENTID] ASC,
[TOTALTIME] DESC
)
INCLUDE ( [URI],
[NETWORKTIME],
[SERVERTIME],
[RESPONSETIME],
[RESPONSESIZE],
[REQUESTSIZE],
[LATENCY]) WITH (SORT_IN_TEMPDB = ON) ON [PRIMARY]
END
GO

EXEC DomainTableRegisterIndexOptimization
@TableName = 'CSAJAX'
,@SchemaName = 'APM'
,@DatasetId = '$Config/DatasetId$'
GO


/*==============================================================*/
/* Table: CSASYNCAJAX */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.CSASYNCAJAX'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.CSASYNCAJAX (
CSASYNCAJAXID int identity,
CSEVENTID int not null,
HANDLERTIME decimal(35) null,
TOTALTIME decimal(35) null,
constraint PK_CSASYNCAJAX primary key (CSASYNCAJAXID)
)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSASYNCAJAX]') AND name = N'idx_EventId'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_EventId] ON APM.CSASYNCAJAX
(
[CSEVENTID] ASC
)
INCLUDE ([HANDLERTIME]) WITH (SORT_IN_TEMPDB = ON)
END
GO

EXEC DomainTableRegisterIndexOptimization
@TableName = 'CSASYNCAJAX'
,@SchemaName = 'APM'
,@DatasetId = '$Config/DatasetId$'
GO

/*==============================================================*/
/* Table: CSEVENT */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.CSEVENT'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.CSEVENT (
CSEVENTID int identity,
CSEVENTGROUPID int not null,
SOURCEID int not null,
MACHINEID int not null,
IPID int null,
CLASSTYPE nvarchar(50) not null,
EVENTCLASS nvarchar(50) null,
PAGEURI nvarchar(255) null,
DESCRIPTION nvarchar(255) not null,
BROWSER nvarchar(255) null,
UTCDATE datetime not null,
ROWGUID nvarchar(15) null,
SEVIEWERDBID int not null,
SEVIEWEREGID int not null,
USERID int null,
PMSTATUS tinyint not null,
TOTALTIME decimal(35) null,
TOTALSIZE bigint null,
LATENCY bigint null,
constraint PK_CSEVENT primary key (CSEVENTID)
)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSEVENT]') AND name = N'FK_USERS'
)
BEGIN
CREATE NONCLUSTERED INDEX FK_USERS ON APM.CSEVENT
(USERID)
END
GO

IF NOT EXISTS (
SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'CSEVENT' AND TABLE_SCHEMA = N'apm' AND COLUMN_NAME = 'PMSTATUS' AND COLUMN_DEFAULT IS NOT NULL
)
BEGIN
ALTER TABLE [APM].[CSEVENT] ADD CONSTRAINT [DF_CSEVENT_PMSTATUS] DEFAULT ((0)) FOR [PMSTATUS]
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSEVENT]') AND name = N'idx_DateSourceClassTypeMachine'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_DateSourceClassTypeMachine] ON [APM].[CSEVENT]
(
[UTCDATE] ASC,
[SOURCEID] ASC,
[CLASSTYPE] ASC,
[MACHINEID] ASC
)
INCLUDE ( [CSEVENTID],
[PAGEURI]) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSEVENT]') AND name = N'idx_ClassTypeDateMachineSource'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_ClassTypeDateMachineSource] ON [APM].[CSEVENT]
(
[CLASSTYPE] ASC,
[UTCDATE] ASC,
[MACHINEID] ASC,
[SOURCEID] ASC
)
INCLUDE([CSEVENTID],
PAGEURI) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSEVENT]') AND name = N'idx_SourceClassTypeDateMachine'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_SourceClassTypeDateMachine] ON [APM].[CSEVENT]
(
[SOURCEID] ASC,
[CLASSTYPE] ASC,
[UTCDATE] ASC,
[MACHINEID] ASC
)
INCLUDE([CSEVENTID],
PAGEURI) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSEVENT]') AND name = N'idx_SourceMachineClassTypeDate'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_SourceMachineClassTypeDate] ON [APM].[CSEVENT]
(
[SOURCEID] ASC,
[MACHINEID] ASC,
[CLASSTYPE] ASC,
[UTCDATE] ASC
)
INCLUDE ( [CSEVENTID],
[PAGEURI]) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSEVENT]') AND name = N'idx_DateSourceClassTypeMachineIpId'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_DateSourceClassTypeMachineIpId] ON [APM].[CSEVENT]
(
[UTCDATE] ASC,
[SOURCEID] ASC,
[CLASSTYPE] ASC,
[MACHINEID] ASC,
[IPID] ASC
)
INCLUDE ( [CSEVENTID],
[CSEVENTGROUPID],
[EVENTCLASS],
[PAGEURI],
[BROWSER],
[DESCRIPTION]) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSEVENT]') AND name = N'idx_SourceMachineEventClassDateIpId'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_SourceMachineEventClassDateIpId] ON [APM].[CSEVENT]
(
[SOURCEID] ASC,
[MACHINEID] ASC,
[EVENTCLASS] ASC,
[UTCDATE] ASC,
[IPID] ASC
)
INCLUDE ( [CSEVENTID],
[CSEVENTGROUPID],
[PAGEURI]) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSEVENT]') AND name = N'idx_DateSourceMachineEventClassIpId'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_DateSourceMachineEventClassIpId] ON [APM].[CSEVENT]
(
[UTCDATE] ASC,
[SOURCEID] ASC,
[MACHINEID] ASC,
[EVENTCLASS] ASC,
[IPID] ASC
)
INCLUDE ( [CSEVENTID],
[CSEVENTGROUPID],
[PAGEURI]) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSEVENT]') AND name = N'FK_IPID'
)
BEGIN
CREATE NONCLUSTERED INDEX [FK_IPID] ON [APM].[CSEVENT]
(
[IPID] ASC
)WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSEVENT]') AND name = N'FK_SOURCEID'
)
BEGIN
CREATE NONCLUSTERED INDEX [FK_SOURCEID] ON [APM].[CSEVENT]
(
[SOURCEID] ASC
) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSEVENT]') AND name = N'idx_SourceEventClassDateMachine'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_SourceEventClassDateMachine] ON [APM].[CSEVENT]
(
[SOURCEID] ASC,
[EVENTCLASS] ASC,
[UTCDATE] ASC,
[MACHINEID] ASC
)
INCLUDE ( [CSEVENTID],
[PAGEURI]) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSEVENT]') AND name = N'idx_DateSourceEventClassMachine'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_DateSourceEventClassMachine] ON [APM].[CSEVENT]
(
[UTCDATE] ASC,
[SOURCEID] ASC,
[EVENTCLASS] ASC,
[MACHINEID] ASC
)
INCLUDE ( [CSEVENTID],
[PAGEURI]) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSEVENT]') AND name = N'idx_ClassTypeSourceMachineDateIpId2'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_ClassTypeSourceMachineDateIpId2] ON [APM].[CSEVENT]
(
[CLASSTYPE] ASC,
[SOURCEID] ASC,
[MACHINEID] ASC,
[UTCDATE] ASC,
[IPID] ASC
)
INCLUDE ( [CSEVENTID],
[CSEVENTGROUPID],
[BROWSER],
[DESCRIPTION]) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSEVENT]') AND name = N'idx_W_PageSourceDate'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_W_PageSourceDate] ON [APM].[CSEVENT]
(
[PAGEURI] ASC,
[SOURCEID] ASC,
[UTCDATE] ASC
)
INCLUDE ( [CLASSTYPE],
[DESCRIPTION],
[ROWGUID],
[SEVIEWEREGID],
[MACHINEID],
[SEVIEWERDBID],
[IPID]) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSEVENT]') AND name = N'idx_SourceMachineClassTypeDateIpId'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_SourceMachineClassTypeDateIpId] ON [APM].[CSEVENT]
(
[SOURCEID] ASC,
[MACHINEID] ASC,
[CLASSTYPE] ASC,
[UTCDATE] ASC,
[IPID] ASC
)
INCLUDE ( [CSEVENTID],
[CSEVENTGROUPID],
[EVENTCLASS],
[PAGEURI],
[BROWSER],
[DESCRIPTION]) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSEVENT]') AND name = N'idx_W_IpIdSourcePageDate'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_W_IpIdSourcePageDate] ON [APM].[CSEVENT]
(
[IPID] ASC,
[SOURCEID] ASC,
[PAGEURI] ASC,
[UTCDATE] ASC
)
INCLUDE ( [CLASSTYPE],
[DESCRIPTION],
[ROWGUID],
[SEVIEWEREGID],
[MACHINEID],
[SEVIEWERDBID]
) WITH (SORT_IN_TEMPDB = ON)
END
GO
------------------------------ Summary User Analysis Indexes ------------------

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSEVENT]') AND name = N'idx_DateSource1'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_DateSource1] ON [APM].[CSEVENT]
(
[UTCDATE] ASC,
[SOURCEID] ASC
)
INCLUDE ( [CSEVENTID],
[CSEVENTGROUPID],
[PAGEURI],
[USERID],
[CLASSTYPE],
[EVENTCLASS],
[MACHINEID],
[BROWSER],
[DESCRIPTION],
[IPID],
[TOTALTIME]) WITH (SORT_IN_TEMPDB = ON) ON [PRIMARY]
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSEVENT]') AND name = N'idx_SourceDate1'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_SourceDate1] ON [APM].[CSEVENT]
(
[SOURCEID] ASC,
[UTCDATE] ASC
)
INCLUDE ( [CSEVENTID],
[CSEVENTGROUPID],
[PAGEURI],
[USERID],
[CLASSTYPE],
[EVENTCLASS],
[MACHINEID],
[BROWSER],
[DESCRIPTION],
[IPID],
[TOTALTIME]) WITH (SORT_IN_TEMPDB = ON) ON [PRIMARY]
END
GO

------------------------------ Transfer indexes--------------------------------
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSEVENT]') AND name = N'idx_T_RowGuid'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_T_RowGuid] ON [APM].[CSEVENT]
(
[ROWGUID] ASC
)WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSEVENT]') AND name = N'idx_T_RowGuid2'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_T_RowGuid2] ON APM.CSEVENT
(
[ROWGUID] ASC
)INCLUDE (UserId) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSEVENT]') AND name = N'idx_T_UtcDate'
)
BEGIN
CREATE INDEX idx_T_UtcDate ON APM.CSEVENT
(UTCDATE)
INCLUDE(SEVIEWERDBID) WITH (SORT_IN_TEMPDB = ON)
END
GO

---------------- delete old sources/computers wizard indexes --------------------
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[csevent]') AND name = N'idx_MachineDate'
)
BEGIN
CREATE INDEX idx_MachineDate ON APM.csevent (MACHINEID, UTCDATE DESC)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSEVENT]') AND name = N'idx_SM_PMStatusDate'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_SM_PMStatusDate] ON [APM].[CSEVENT]
(
[PMSTATUS] ASC,
[UTCDATE] ASC
)
INCLUDE ( [SEVIEWERDBID],
[CSEVENTID])
END
GO

EXEC DomainTableRegisterIndexOptimization
@TableName = 'CSEVENT'
,@SchemaName = 'APM'
,@DatasetId = '$Config/DatasetId$'
GO

/*==============================================================*/
/* Table: CSEVENTGROUP */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.CSEVENTGROUP'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.CSEVENTGROUP (
CSEVENTGROUPID int identity,
FIRSTEVENTDATE datetime not null,
LASTEVENTDATE datetime not null,
HASHVALUE nvarchar(50) null,
DESCRIPTION nvarchar(255) null,
SOURCEID int null,
constraint PK_CSEVENTGROUP primary key (CSEVENTGROUPID)
)
END
GO

------------------ Transfer indexes -----------------------
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSEventGroup]') AND name = N'idx_T_hashvalue'
)
BEGIN
CREATE INDEX idx_T_hashvalue on APM.CSEventGroup(hashvalue) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSEVENTGROUP]') AND name = N'idx_T_hashvalue2'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_T_hashvalue2] ON APM.CSEVENTGROUP
(
[HASHVALUE] ASC
) include (firsteventdate, lasteventdate, sourceid) WITH (SORT_IN_TEMPDB = ON)
END
GO

EXEC DomainTableRegisterIndexOptimization
@TableName = 'CSEVENTGROUP'
,@SchemaName = 'APM'
,@DatasetId = '$Config/DatasetId$'
GO

/*==============================================================*/
/* Table: CSEXEVENT */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.CSEXEVENT'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.CSEXEVENT (
CSEXEVENTID int identity,
CSEVENTID int not null,
ACTION nvarchar(255) not null,
EXMESSAGE nvarchar(255) not null,
EXTYPE nvarchar(255) not null,
EXFUNCTION nvarchar(255) not null,
ROWGUID nvarchar(15) null,
constraint PK_CSEXEVENT primary key (CSEXEVENTID)
)
END
GO

/*==============================================================*/
/* Table: CSHEAVIESTRESOURCE */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.CSHEAVIESTRESOURCE'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.CSHEAVIESTRESOURCE (
CSHEAVIESTRESOURCEID int identity,
CSEVENTID int not null,
NAME nvarchar(255) not null,
DURATION decimal(35) not null,
ROWGUID nvarchar(15) null,
ISHEAVIESTNODE bit not null,
constraint PK_CSHEAVIESTRESOURCE primary key (CSHEAVIESTRESOURCEID)
)
END
GO

IF NOT EXISTS (
SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'CSHEAVIESTRESOURCE' AND TABLE_SCHEMA = N'apm' AND COLUMN_NAME = 'IsHeaviestNode' AND COLUMN_DEFAULT IS NOT NULL
)
BEGIN
ALTER TABLE APM.CSHEAVIESTRESOURCE ADD CONSTRAINT DF_CSHEAVIESTRESOURCE_ISHAVIESTNODE DEFAULT 0 FOR IsHeaviestNode
END
GO

---------------------Transfer indexes---------------------
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSHEAVIESTRESOURCE]') AND name = N'idx_T_RowGuid'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_T_RowGuid] ON APM.CSHEAVIESTRESOURCE
(
[ROWGUID] ASC
) WITH (SORT_IN_TEMPDB = ON)
END
GO

EXEC DomainTableRegisterIndexOptimization
@TableName = 'CSHEAVIESTRESOURCE'
,@SchemaName = 'APM'
,@DatasetId = '$Config/DatasetId$'
GO

/*==============================================================*/
/* Table: CSJSCRIPTEVENT */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.CSJSCRIPTEVENT'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.CSJSCRIPTEVENT (
CSJSCRIPTEVENTID int identity,
CSEVENTID int not null,
ACTION nvarchar(255) not null,
TOTALTIME decimal(35) null,
UTCDATE datetime null,
SOURCEID int null,
constraint PK_CSJSCRIPTEVENT primary key (CSJSCRIPTEVENTID)
)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSJSCRIPTEVENT]') AND name = N'idx_W_ActionEvent'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_W_ActionEvent] ON [APM].[CSJSCRIPTEVENT]
(
[ACTION] ASC,
[CSEVENTID] ASC

) INCLUDE([TOTALTIME])
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSJSCRIPTEVENT]') AND name = N'idx_W_EventAction'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_W_EventAction] ON [APM].[CSJSCRIPTEVENT]
(
[CSEVENTID] ASC,
[ACTION] ASC

) INCLUDE([TOTALTIME])
WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSJSCRIPTEVENT]') AND name = N'FK_CSEVENTID'
)
BEGIN
CREATE NONCLUSTERED INDEX [FK_CSEVENTID] ON [APM].[CSJSCRIPTEVENT]
(
[CSEVENTID] ASC
)WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSJSCRIPTEVENT]') AND name = N'idx_CSEvent1'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_CSEvent1] ON APM.CSJSCRIPTEVENT
(
[CSEVENTID] ASC
)
INCLUDE (
[TOTALTIME],
[ACTION]) WITH (SORT_IN_TEMPDB = ON)
END
GO

EXEC DomainTableRegisterIndexOptimization
@TableName = 'CSJSCRIPTEVENT'
,@SchemaName = 'APM'
,@DatasetId = '$Config/DatasetId$'
GO

/*==============================================================*/
/* Table: CSPAGEEVENT */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.CSPAGEEVENT'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.CSPAGEEVENT (
CSPAGEEVENTID int identity,
CSEVENTID int not null,
NETWORKTIME decimal(35) null,
SERVERTIME decimal(35) null,
DOMTIME decimal(35) null,
PERIPHERALTIME decimal(35) null,
ONLOADTIME decimal(35) null,
TOTALTIME decimal(35) null,
TOTALSIZE bigint null,
LATENCY bigint null,
UTCDATE datetime null,
SOURCEID int null,
constraint PK_CSPAGEEVENT primary key (CSPAGEEVENTID)
)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSPAGEEVENT]') AND name = N'FK_CSEVENTID'
)
BEGIN
CREATE NONCLUSTERED INDEX [FK_CSEVENTID] ON [APM].[CSPAGEEVENT]
(
[CSEVENTID] ASC
)WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSPAGEEVENT]') AND name = N'idx_EventId1'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_EventId1] ON [APM].[CSPAGEEVENT]
(
[CSEVENTID] ASC
)
INCLUDE ( [TOTALTIME],
[TOTALSIZE],
[NETWORKTIME],
[SERVERTIME],
[DOMTIME],
[PERIPHERALTIME],
[ONLOADTIME],
[LATENCY]
) WITH (SORT_IN_TEMPDB = ON)
END
GO

EXEC DomainTableRegisterIndexOptimization
@TableName = 'CSPAGEEVENT'
,@SchemaName = 'APM'
,@DatasetId = '$Config/DatasetId$'
GO

/*==============================================================*/
/* Table: CSPERIPHERAL */
/*==============================================================*/

IF (OBJECTPROPERTY(OBJECT_ID('APM.CSPERIPHERAL'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.CSPERIPHERAL (
CSPERIPHERALID int identity,
CSEVENTID int not null,
TYPE nvarchar(50) not null,
TOTALSIZE bigint null,
TOTALTIME decimal(35) null,
constraint PK_CSPERIPHERAL primary key (CSPERIPHERALID)
)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSPERIPHERAL]') AND name = N'FK_CSEVENTID'
)
BEGIN
CREATE NONCLUSTERED INDEX [FK_CSEVENTID] ON [APM].[CSPERIPHERAL]
(
[CSEVENTID] ASC
)WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSPERIPHERAL]') AND name = N'idx_EventId'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_EventId] ON [APM].[CSPERIPHERAL]
(
[CSEVENTID] ASC
)
INCLUDE ( [TYPE],
[TOTALSIZE]) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSPERIPHERAL]') AND name = N'idx_EventPeripheral'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_EventPeripheral] ON [APM].[CSPERIPHERAL]
(
[CSEVENTID] ASC,
[CSPERIPHERALID] ASC
)
INCLUDE ( [TYPE],
[TOTALSIZE]) WITH (SORT_IN_TEMPDB = ON)
END
GO

------------------------------ Transfer indexes -------------------------
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSPERIPHERAL]') AND name = N'idx_T_EventIdType'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_T_EventIdType] ON APM.CSPERIPHERAL
(
[CSEVENTID] ASC,
[TYPE] ASC
) WITH (SORT_IN_TEMPDB = ON)
END
GO

EXEC DomainTableRegisterIndexOptimization
@TableName = 'CSPERIPHERAL'
,@SchemaName = 'APM'
,@DatasetId = '$Config/DatasetId$'
GO

/*==============================================================*/
/* Table: CSPERIPHERALDETAIL */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.CSPERIPHERALDETAIL'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.CSPERIPHERALDETAIL (
CSPERIPHERALDETAILID int identity,
CSPERIPHERALID int not null,
DOMAIN nvarchar(255) not null,
PATH nvarchar(255) not null,
SIZE bigint null,
TOTALTIME decimal(35) null,
constraint PK_CSPERIPHERALDETAIL primary key (CSPERIPHERALDETAILID)
)
END
GO

/*==============================================================*/
/* Table: DATASET */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.DATASET'), 'IsTable') IS NULL)
BEGIN
-- Create table
CREATE TABLE APM.DATASET (
DATASETID int identity,
AGGREGATIONTYPEID int null,
DATASETNAME nvarchar(50) not null,
DEFAULTAGGREGATIONINTERVALCOUNT tinyint not null,
MAXDATAAGEDAYS int null,
AGGREGATIONMETHODNAME nvarchar(50) null,
constraint PK_DATASET primary key (DATASETID)
)

--Insert default values
INSERT into APM.dataset (
DATASETNAME
,DEFAULTAGGREGATIONINTERVALCOUNT
,AGGREGATIONTYPEID
,AGGREGATIONMETHODNAME
,MAXDATAAGEDAYS
)
values (
N'perfHourly',
40,
30,
N'PCounterAggregate',
91
)
END
GO

/*==============================================================*/
/* Table: DATASETAGGREGATIONHISTORY */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.DATASETAGGREGATIONHISTORY'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.DATASETAGGREGATIONHISTORY (
DATASETAGGREGATIONHISTORYID int identity,
DATASETID int not null,
AGGREGATIONDATETIME datetime not null,
DIRTYIND bit not null,
constraint PK_DATASETAGGREGATIONHISTORY primary key (DATASETAGGREGATIONHISTORYID)
)
END
GO

IF NOT EXISTS (
SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'DatasetAggregationHistory' AND TABLE_SCHEMA = N'apm' AND COLUMN_NAME = 'DirtyInd' AND COLUMN_DEFAULT IS NOT NULL
)
BEGIN
ALTER TABLE APM.DatasetAggregationHistory ADD CONSTRAINT DatasetAggregationHistoryID_Default DEFAULT 1 FOR DirtyInd
END
GO

--------------------------------------- Transfer indexes ----------------------
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[DATASETAGGREGATIONHISTORY]') AND name = N'idx_T_DIRTYIND_datasetid_date'
)
BEGIN
CREATE INDEX idx_T_DIRTYIND_datasetid_date ON APM.DATASETAGGREGATIONHISTORY
(
DIRTYIND, datasetid, AGGREGATIONDATETIME
)
WITH (SORT_IN_TEMPDB = ON)
END
GO

EXEC DomainTableRegisterIndexOptimization
@TableName = 'DATASETAGGREGATIONHISTORY'
,@SchemaName = 'APM'
,@DatasetId = '$Config/DatasetId$'
GO

/*==============================================================*/
/* Table: EVENT */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.EVENT'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.EVENT (
EVENTID bigint identity,
EVENTGROUPID int null,
RESOURCEID int null,
SOURCEID int null,
EVENTDURATION decimal(35) null,
MACHINEID int not null,
UTCEVENTDATE datetime not null,
EVENTCLASSTYPE nvarchar(50) null,
ROOTNODENAME nvarchar(255) null,
ASPECT nvarchar(50) null,
EXCEPTIONCLASS nvarchar(255) null,
DESCRIPTION nvarchar(255) null,
CATEGORY nvarchar(50) null,
HEAVYLIGHT int null,
ROWGUID nvarchar(15) null,
SEVIEWERDBID int null,
SEVIEWEREGID int not null,
IPID int null,
USERID int null,
PMSTATUS tinyint not null
)

ALTER TABLE APM.Event
ADD CONSTRAINT PK_EVENT PRIMARY KEY NONCLUSTERED (EVENTID)
END
GO

/*==============================================================*/
/* Index: IX_CDATE */
/*==============================================================*/
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[Event]') AND name = N'IX_CDATE'
)
BEGIN
CREATE CLUSTERED INDEX IX_CDATE ON APM.Event
(
UTCEVENTDATE ASC
)
END
GO

IF NOT EXISTS (
SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'EVENT' AND TABLE_SCHEMA = N'apm' AND COLUMN_NAME = 'PMSTATUS' AND COLUMN_DEFAULT IS NOT NULL
)
BEGIN
ALTER TABLE [APM].[EVENT] ADD CONSTRAINT [DF_EVENT_PMSTATUS] DEFAULT ((0)) FOR [PMSTATUS]
END
GO

--------------------- Change foreign key index--------------------------
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[EVENT]') AND name = N'FK_EVENTGROUP'
)
BEGIN
CREATE NONCLUSTERED INDEX [FK_EVENTGROUP] ON [APM].[EVENT]
(
[EVENTGROUPID] ASC
)
INCLUDE ( [EVENTDURATION],
[MACHINEID],
[UTCEVENTDATE],
[EVENTID],
[SOURCEID],
[EVENTCLASSTYPE],
[rootnodename],
[DESCRIPTION],
[CATEGORY]) WITH (SORT_IN_TEMPDB = ON)
END
GO

-----------------End Change foreign key index---------------------------
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[EVENT]') AND name = N'idx_DateSourceMachine'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_DateSourceMachine] ON [APM].[EVENT]
(
[UTCEVENTDATE] ASC,
[SOURCEID] ASC,
[MACHINEID] ASC
)
INCLUDE ( [EVENTGROUPID],
[EVENTDURATION],
[CATEGORY],
[HEAVYLIGHT],
[ASPECT],
[RESOURCEID],
[EVENTCLASSTYPE],
[USERID],
[EVENTID],
[DESCRIPTION],
[SEVIEWERDBID],
[ROOTNODENAME]) WITH (SORT_IN_TEMPDB = ON) ON [PRIMARY]
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[EVENT]') AND name = N'idx_MachineDate'
)
BEGIN
CREATE NONCLUSTERED INDEX idx_MachineDate ON APM.EVENT
(
MACHINEID
,UTCEVENTDATE
)
INCLUDE
(
SOURCEID
,EVENTGROUPID
,EVENTDURATION
,CATEGORY
,HEAVYLIGHT
,ASPECT
,RESOURCEID
,EVENTCLASSTYPE
,USERID
,EVENTID
,DESCRIPTION
,SEVIEWERDBID
,ROOTNODENAME
,[PMSTATUS]
)
WITH (SORT_IN_TEMPDB = ON) ON [PRIMARY]
END
GO

--------------------------------- Transfer indexes --------------
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[EVENT]') AND name = N'idx_T_RowGuid'
)
BEGIN
CREATE NONCLUSTERED INDEX idx_T_RowGuid ON APM.EVENT
(
ROWGUID
)
INCLUDE
(
HEAVYLIGHT
,IPID
,EVENTID
,USERID
)
WITH (SORT_IN_TEMPDB = ON) ON [PRIMARY]
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[EVENT]') AND name = N'idx_T_ResourceIdEventClassTypeDB'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_T_ResourceIdEventClassTypeDB] ON [APM].[EVENT]
(
[RESOURCEID] ASC,
[EVENTCLASSTYPE] ASC,
[SEVIEWERDBID] ASC
)
INCLUDE ( [HEAVYLIGHT],
[ROWGUID],
[EVENTID],
[SOURCEID],
[MACHINEID],
[EVENTDURATION]) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[EVENT]') AND name = N'idx_T_EventId'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_T_EventId] ON [APM].[EVENT]
(
[EVENTID] ASC
)
INCLUDE ( [SEVIEWERDBID],
[HEAVYLIGHT],
[ROWGUID],
[EXCEPTIONCLASS],
[DESCRIPTION],
[EVENTDURATION],
[SOURCEID],
[EVENTCLASSTYPE],
[RESOURCEID]) WITH (SORT_IN_TEMPDB = ON) ON [PRIMARY]
END
GO

----------------------- Event Window Indexes ----------------------
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[Event]') AND name = N'idx_W_ResourceDate'
)
BEGIN
CREATE INDEX idx_W_ResourceDate ON APM.Event
(ResourceId, UtcEventDate)
INCLUDE(
[SourceId],
[EventId],
[EventDuration],
[MACHINEID],
[EVENTCLASSTYPE],
[RootNodeName],
[DESCRIPTION],
[CATEGORY],
[ROWGUID],
[Aspect],
[HeavyLight],
[SEVIEWERDBID],
[SEVIEWEREGID],
[USERID],
[EVENTGROUPID]
) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[Event]') AND name = N'idx_W_SourceDate'
)
BEGIN
CREATE INDEX idx_W_SourceDate ON APM.Event
(SourceId, UtcEventDate)
INCLUDE(
[RESOURCEID],
[EventId],
[EventDuration],
[MACHINEID],
[EVENTCLASSTYPE],
[RootNodeName],
[DESCRIPTION],
[CATEGORY],
[ROWGUID],
[Aspect],
[HeavyLight],
[SEVIEWERDBID],
[SEVIEWEREGID],
[EVENTGROUPID],
[USERID]
) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[Event]') AND name = N'idx_W_RootDate'
)
BEGIN
CREATE INDEX idx_W_RootDate ON APM.Event
(RootNodeName, UTCEVENTDATE)
INCLUDE(
[SourceId],
[MachineId],
[RESOURCEID],
[EVENTID],
[EVENTDURATION],
[EVENTCLASSTYPE],
[DESCRIPTION],
[CATEGORY],
[ROWGUID],
[Aspect],
[Heavylight],
[SEVIEWERDBID],
[SEVIEWEREGID],
[EVENTGROUPID],
[USERID]
) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[EVENT]') AND name = N'idx_W_DescriptionDate'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_W_DescriptionDate] ON [APM].[EVENT]
(
[DESCRIPTION] ASC,
[UTCEVENTDATE] ASC
)
INCLUDE ( [SOURCEID],
[MACHINEID],
[RESOURCEID],
[ROOTNODENAME],
[CATEGORY],
[EVENTID],
[EVENTCLASSTYPE],
[ROWGUID],
[ASPECT],
[HEAVYLIGHT],
[SEVIEWERDBID],
[SEVIEWEREGID],
[USERID]) WITH (SORT_IN_TEMPDB = ON)
END
GO

/*==============================================================*/
/* Index: FK_EVENTRESOURCEID */
/*==============================================================*/
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[EVENT]') AND name = N'FK_EVENTRESOURCEID'
)
BEGIN
CREATE INDEX FK_EVENTRESOURCEID on APM.EVENT (
RESOURCEID ASC
)
END
GO

/*==============================================================*/
/* Index: FK_EVENTMACHINEID */
/*==============================================================*/
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[EVENT]') AND name = N'FK_EVENTMACHINEID'
)
BEGIN
CREATE INDEX FK_EVENTMACHINEID on APM.EVENT (
MACHINEID ASC
)
END
GO

/*==============================================================*/
/* Index: FK_EVENTSOURCEID */
/*==============================================================*/
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[EVENT]') AND name = N'FK_EVENTSOURCEID'
)
BEGIN
CREATE INDEX FK_EVENTSOURCEID on APM.EVENT (
SOURCEID ASC
)
END
GO

/*==============================================================*/
/* Index: FK_IPID */
/*==============================================================*/
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[EVENT]') AND name = N'FK_IPID'
)
BEGIN
CREATE INDEX FK_IPID on APM.EVENT (
IPID ASC
)
END
GO

/*==============================================================*/
/* Index: FK_SEVIEWERDBID */
/*==============================================================*/
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[EVENT]') AND name = N'FK_SEVIEWERDBID'
)
BEGIN
CREATE INDEX FK_SEVIEWERDBID on APM.EVENT (
SEVIEWERDBID ASC
)
END
GO

/*==============================================================*/
/* Index: FK_USERS */
/*==============================================================*/
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[EVENT]') AND name = N'FK_USERS'
)
BEGIN
CREATE INDEX FK_USERS on APM.EVENT (
USERID ASC
)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[EVENT]') AND name = N'idx_SM_PMStatusDate'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_SM_PMStatusDate] ON [APM].[EVENT]
(
[PMSTATUS] ASC,
[UTCEVENTDATE] ASC
)
INCLUDE ( [SEVIEWERDBID],
[EVENTID])
END
GO

EXEC DomainTableRegisterIndexOptimization
@TableName = 'EVENT'
,@SchemaName = 'APM'
,@DatasetId = '$Config/DatasetId$'
GO

/*==============================================================*/
/* Table: EVENTGROUP */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.EVENTGROUP'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.EVENTGROUP (
EVENTGROUPID int identity,
FIRSTEVENTDATE datetime null,
LASTEVENTDATE datetime null,
EVENTCLASSTYPE nvarchar(50) null,
ROOTNODENAME nvarchar(255) null,
ASPECT nvarchar(50) null,
HASHVALUE nvarchar(50) null,
DESCRIPTION nvarchar(255) null,
SOURCEID int null,
constraint PK_EVENTGROUP primary key (EVENTGROUPID)
)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[EVENTGROUP]') AND name = N'idx_EventGroupIdFirstEventDateSource'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_EventGroupIdFirstEventDateSource] ON [APM].[EVENTGROUP]
(
[EVENTGROUPID] ASC,
[FIRSTEVENTDATE] ASC,
[SOURCEID] ASC
) WITH (SORT_IN_TEMPDB = ON)
END
GO

-----------------------Transfer indexed----------------------
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[EVENTGROUP]') AND name = N'idx_EVENTGROUP_LASTEVENTDATE'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_EVENTGROUP_LASTEVENTDATE] ON APM.EVENTGROUP
(
[LASTEVENTDATE]
) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSEVENTGROUP]') AND name = N'idx_CSEVENTGROUP_LASTEVENTDATE'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_CSEVENTGROUP_LASTEVENTDATE] ON APM.CSEVENTGROUP
(
[LASTEVENTDATE]
) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[EVENTGROUP]') AND name = N'idx_T_hashvalue'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_T_hashvalue] ON [APM].[EVENTGROUP]
(
[HASHVALUE] ASC
) INCLUDE (firsteventdate, lasteventdate, sourceid) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[EVENTGROUP]') AND name = N'ix_T_hashvalue2'
)
BEGIN
CREATE NONCLUSTERED INDEX [ix_T_hashvalue2] ON [APM].[EVENTGROUP]
(
[HASHVALUE] ASC
) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[EVENTGROUP]') AND name = N'idx_EventGroupIdFirstEventDate'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_EventGroupIdFirstEventDate] ON APM.EVENTGROUP
(
[EVENTGROUPID] ASC,
[FIRSTEVENTDATE] ASC
)
WITH (SORT_IN_TEMPDB = ON)
END
GO

EXEC DomainTableRegisterIndexOptimization
@TableName = 'EVENTGROUP'
,@SchemaName = 'APM'
,@DatasetId = '$Config/DatasetId$'
GO

/*==============================================================*/
/* Table: EXCEPTIONNODE */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.EXCEPTIONNODE'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.EXCEPTIONNODE (
EXCEPTIONNODEID bigint identity,
EVENTID bigint not null,
RESOURCEID int null,
EXCEPTIONMESSAGE nvarchar(255) null,
EXCEPTIONCLASS nvarchar(255) null,
FUNCTIONNAME nvarchar(255) null,
RESOURCEMETHOD nvarchar(255) null,
MODULENAME nvarchar(255) null,
LINENUMBER bigint null,
DESCRIPTION nvarchar(255) null,
HASHCODE nvarchar(255) null,
ENTRYID int null,
ROWGUID nvarchar(15) null,
constraint PK_EXCEPTIONNODE primary key (EXCEPTIONNODEID)
)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[EXCEPTIONNODE]') AND name = N'idx_EVENTID'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_EVENTID] ON [APM].[EXCEPTIONNODE]
(
[EVENTID] ASC
)
INCLUDE ( [RESOURCEMETHOD]) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[EXCEPTIONNODE]') AND name = N'idx_ResourceExceptionEvent'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_ResourceExceptionEvent] ON [APM].[EXCEPTIONNODE]
(
[RESOURCEID] ASC,
[EXCEPTIONNODEID] ASC,
[EVENTID] ASC
)
INCLUDE ( [RESOURCEMETHOD]) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[EXCEPTIONNODE]') AND name = N'idx_EventIdResource2'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_EventIdResource2] ON [APM].[EXCEPTIONNODE]
(
[EVENTID] ASC,
[ResourceId] ASC
)
INCLUDE ( [RESOURCEMETHOD]) WITH (SORT_IN_TEMPDB = ON)
END
GO

----------------------Summary User Analysis Report -------------------
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[ExceptionNode]') AND name = N'idx_EventIdResource'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_EventIdResource] ON [APM].[ExceptionNode]
(
[EVENTID] ASC,
[RESOURCEID] ASC
)
INCLUDE ( [DESCRIPTION]) WITH (SORT_IN_TEMPDB = ON)
END
GO

----------------------Transfer indexes ------------------------------
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[EXCEPTIONNODE]') AND name = N'idx_T_eventIdResourceId'
)
BEGIN
CREATE INDEX idx_T_eventIdResourceId on APM.exceptionnode(eventid, resourceid) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[EXCEPTIONNODE]') AND name = N'idx_T_rowguid'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_T_rowguid] ON [APM].[EXCEPTIONNODE]
(
[ROWGUID] ASC
) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[EXCEPTIONNODE]') AND name = N'idx_T_eventId'
)
BEGIN
CREATE INDEX idx_T_eventId on APM.EXCEPTIONNODE(eventid)
INCLUDE(resourceid) WITH (SORT_IN_TEMPDB = ON)
END
GO

----------------------- Event Window indexes ---------------------------------
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[ExceptionNode]') AND name = N'idx_W_ResourceMethod'
)
BEGIN
CREATE INDEX idx_W_ResourceMethod on APM.ExceptionNode (RESOURCEMETHOD) INCLUDE(Eventid) WITH (SORT_IN_TEMPDB = ON)
END
GO

/*==============================================================*/
/* Index: IX_XDATA_HASHCODE */
/*==============================================================*/
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[EXCEPTIONNODE]') AND name = N'IX_XDATA_HASHCODE'
)
BEGIN
create index IX_XDATA_HASHCODE on APM.EXCEPTIONNODE (
HASHCODE ASC
)
END
GO

/*==============================================================*/
/* Index: FK_EXCEPTIONNODERESOURCEID */
/*==============================================================*/
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[EXCEPTIONNODE]') AND name = N'FK_EXCEPTIONNODERESOURCEID'
)
BEGIN
create index FK_EXCEPTIONNODERESOURCEID on APM.EXCEPTIONNODE (
RESOURCEID ASC
)
END
GO

/*==============================================================*/
/* Index: FK_EXCEPTIONNODEEVENTID */
/*==============================================================*/
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[EXCEPTIONNODE]') AND name = N'FK_EXCEPTIONNODEEVENTID'
)
BEGIN
create index FK_EXCEPTIONNODEEVENTID on APM.EXCEPTIONNODE (
EVENTID ASC
)
END
GO

/*==============================================================*/
/* Index: FK_EXCEPTIONNODEEVENTIDRESOURCEID */
/*==============================================================*/
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[EXCEPTIONNODE]') AND name = N'FK_EXCEPTIONNODEEVENTIDRESOURCEID'
)
BEGIN
create index FK_EXCEPTIONNODEEVENTIDRESOURCEID on APM.EXCEPTIONNODE (
EVENTID ASC,
RESOURCEID ASC
)
END
GO

EXEC DomainTableRegisterIndexOptimization
@TableName = 'EXCEPTIONNODE'
,@SchemaName = 'APM'
,@DatasetId = '$Config/DatasetId$'
GO

/*==============================================================*/
/* Table: IP */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.IP'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.IP (
IPID int identity,
IP nvarchar(50) not null,
SUBNETC nvarchar(50) not null,
constraint PK_IP primary key (IPID)
)
END
GO

IF NOT EXISTS
(
SELECT * FROM INFORMATION_SCHEMA.table_constraints WHERE TABLE_NAME = N'IP' AND TABLE_SCHEMA = N'apm' AND CONSTRAINT_NAME=N'uniq_ip'
)
BEGIN
ALTER TABLE APM.ip ADD CONSTRAINT uniq_ip UNIQUE (ip)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[IP]') AND name = N'idx_IP'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_IP] ON [APM].[IP]
(
[IPID] ASC
)
INCLUDE ([SUBNETC]) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[IP]') AND name = N'idx_IPSubnetC'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_IPSubnetC] ON [APM].[IP]
(
[IPID] ASC,
[SUBNETC] ASC
)
END
GO

EXEC DomainTableRegisterIndexOptimization
@TableName = 'IP'
,@SchemaName = 'APM'
,@DatasetId = '$Config/DatasetId$'
GO

/*==============================================================*/
/* Table: MACHINE */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.MACHINE'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.MACHINE (
MACHINEID int identity,
MACHINE nvarchar(255) NOT NULL,
WINDOWSVERSION nvarchar(50) NULL,
AGENTVERSION nvarchar(50) NULL,
CPUCOUNT int NULL,
CONSTRAINT PK_MACHINE primary key (MACHINEID),
CONSTRAINT UC_MACHINE_MACHINE UNIQUE (MACHINE)
)
END
GO

/*==============================================================*/
/* Index: IX_MACHINE */
/*==============================================================*/
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[MACHINE]') AND name = N'IX_MACHINE'
)
BEGIN
create unique index IX_MACHINE on APM.MACHINE (
MACHINE ASC
)
END
GO

/*==============================================================*/
/* Table: MEMBER */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.MEMBER'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.MEMBER (
MEMBERID int not null,
LOGINNAME nvarchar(50) not null,
MEMBERPASSWORD nvarchar(255) null,
FIRSTNAME nvarchar(50) null,
LASTNAME nvarchar(50) null,
EMAIL nvarchar(255) null,
USERDATA ntext null,
USERTYPE char(1) null,
constraint PK_MEMBER primary key nonclustered (MEMBERID)
)
END
GO

/*==============================================================*/
/* Index: IX_LOGINNAME */
/*==============================================================*/
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[MEMBER]') AND name = N'IX_LOGINNAME'
)
BEGIN
create unique index IX_LOGINNAME on APM.MEMBER (
LOGINNAME ASC
)
END
GO

/*==============================================================*/
/* Table: MEMBERAPPLICATION */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.MEMBERAPPLICATION'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.MEMBERAPPLICATION (
MEMBERAPPLICATIONID int not null,
APPLICATIONID int null,
MEMBERID int null,
constraint PK_MEMBERAPPLICATION primary key nonclustered (MEMBERAPPLICATIONID)
)
END
GO

/*==============================================================*/
/* Index: FK_FK_APPLICATION */
/*==============================================================*/
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[MEMBERAPPLICATION]') AND name = N'FK_FK_APPLICATION'
)
BEGIN
create index FK_FK_APPLICATION on APM.MEMBERAPPLICATION (
APPLICATIONID ASC
)
END
GO

/*==============================================================*/
/* Index: FK_FK_USER */
/*==============================================================*/
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[MEMBERAPPLICATION]') AND name = N'FK_FK_USER'
)
BEGIN
create index FK_FK_USER on APM.MEMBERAPPLICATION (
MEMBERID ASC
)
END
GO

/*==============================================================*/
/* Table: MESSAGES */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.MESSAGES'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.MESSAGES (
ID int not null,
MESSAGE nvarchar(max) not null,
constraint PK_MESSAGES primary key (ID)
)

insert APM.messages values(50002, N'stored procedure %s: sp_xml_preparedocument has returned error code %d ')
insert APM.messages values(50004, N'There was an error %d. Severity level: %d Error state: %d Procedure: %s Line: %d Message: %s ')
INSERT APM.MESSAGES VALUES(50006, N'stored procedure %s: Event with RowGuid %s was not found.')
INSERT APM.MESSAGES VALUES(50007, N'FillGroups: document is empty.')
INSERT APM.MESSAGES VALUES(50008, N'FillGroups: Inserted %d resource group.')
INSERT APM.MESSAGES VALUES(50010, N'FillGroups: Inserted %d resource group node.')
INSERT APM.MESSAGES VALUES(50011, N'FILLINTERNALRESOURCES: performance events exist without performance nodes.')
INSERT APM.MESSAGES VALUES(50012, N'FILLINTERNALRESOURCES: exception events exist without exception nodes.')
INSERT APM.MESSAGES VALUES(50013, N'FILLRESOURCES: #DETAILS is empty.')
INSERT APM.MESSAGES VALUES(50014, N'FILLRESOURCES: INSERTED INTO RESOURCE %d record(s).')
INSERT APM.MESSAGES VALUES(50015, N'FILLRESOURCES: heaviest nodes exist.')
INSERT APM.MESSAGES VALUES(50016, N'FILLRESOURCES: Performance node is missing for the heaviest resource.')
INSERT APM.MESSAGES VALUES(50017, N'FILLRESOURCES: Created %d performancenode record(s) for missing heaviest nodes.')
INSERT APM.MESSAGES VALUES(50018, N'FILLRESOURCES: Updated %d performancenode record(s) for resources that contain references to the resource group node.')
INSERT APM.MESSAGES VALUES(50019, N'FILLRESOURCES: Updated %d performancenode record(s) for resources that do not contains references to the resource group node.')
INSERT APM.MESSAGES VALUES(50020, N'FILLRESOURCES: Updated %d event record(s). Save references to the top heaviest resource.')
INSERT APM.MESSAGES VALUES(50021, N'FILLRESOURCES: Updated %d exceptionnode record(s). Save references to the exception method.')
INSERT APM.MESSAGES VALUES(50022, N'FILLRESOURCES: Updated %d event record(s). Save references to the exception method.')
INSERT APM.MESSAGES VALUES(50023, N'GROOMINGWORKTABLES: Deleted %d record(s) from %s table.')

INSERT APM.MESSAGES VALUES(50024, N'CLIENTEVENT_SYNC: Inserted %d record(s) into %s table.')
INSERT APM.MESSAGES VALUES(50025, N'CLIENTEVENT_SYNC: performance events exist.')
INSERT APM.MESSAGES VALUES(50026, N'CLIENTEVENT_SYNC: AJAX events exist.')

INSERT APM.MESSAGES VALUES(50027, N'FILLINTERNALRESOURCES: Resource group nodes were not found.')
INSERT APM.MESSAGES VALUES(50028, N'FILLINTERNALRESOURCES: Processed %d record(s). Inserted %d record(s) into the performance node table.')
INSERT APM.MESSAGES VALUES(50029, N'FILLINTERNALRESOURCES: Inserted %d record(s) into the exception node table.')
INSERT APM.MESSAGES VALUES(50030, N'stored procedure %s: Event with RowGuid %s was not found.')

INSERT APM.MESSAGES VALUES(50031, N'FILLRESOURCEGROUPNODES: Resource group node is missing.')
INSERT APM.MESSAGES VALUES(50032, N'%s: Inserted %d record(s) into %s table.')
INSERT APM.MESSAGES VALUES(50033, N'GroomingWorkTables: package size %d, period(days) %d, reporting grooming date %s.')
INSERT APM.MESSAGES VALUES(50034, N'GROOMINGWORKTABLES: pmstatus - %d lifetime - %d (hours) last keep date - %s.')
INSERT APM.MESSAGES VALUES(50035, N'FILLINTERNALRESOURCES: rowguid(s) "%s" or "%s" have not been found.')
END
GO

/*==============================================================*/
/* Table: OPERATION */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.OPERATION'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.OPERATION (
OPERATIONID int not null,
OPERATIONNAME nvarchar(50) not null,
REPEATCOUNTONFAILED int not null,
constraint PK_OPERATION primary key (OPERATIONID)
)

insert into APM.operation values(1, 'extraction', 0)
insert into APM.operation values(2, 'transform', 0)
insert into APM.operation values(3, 'insert', 0)
insert into APM.operation values(4, 'update', 0)
insert into APM.operation values(5, 'aggregate', 0)
insert into APM.operation values(6, 'grooming', 0)
insert into APM.operation values(7, 'constraints', 0)
insert into APM.operation values(8, 'resource', 0)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[OPERATION]') AND name = N'OperationName_IX'
)
BEGIN
CREATE UNIQUE INDEX OperationName_IX ON APM.OPERATION (OperationName)
END
GO

EXEC DomainTableRegisterIndexOptimization
@TableName = 'OPERATION'
,@SchemaName = 'APM'
,@DatasetId = '$Config/DatasetId$'
GO

/*==============================================================*/
/* Table: PCDESCRIPTION */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.PCDESCRIPTION'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.PCDESCRIPTION (
PCDESCRIPTIONID int identity,
NAME nvarchar(255) not null,
DESCRIPTION ntext null,
constraint PK_PCDESCRIPTION primary key (PCDESCRIPTIONID)
)
END
GO

/*==============================================================*/
/* Index: IX_NAME */
/*==============================================================*/
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PCDESCRIPTION]') AND name = N'IX_NAME'
)
BEGIN
create unique index IX_NAME on APM.PCDESCRIPTION (
NAME ASC
)
END
GO

/*==============================================================*/
/* Table: PCPROCESS */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.PCPROCESS'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.PCPROCESS (
PCPROCESSID int identity,
PROCESS nvarchar(255) NULL,
EXTRATYPE int NULL,
EXTRAINFO nvarchar(255) NULL,
HASHVALUE nvarchar(50) NULL,
CONSTRAINT PK_PCPROCESS primary key (PCPROCESSID),
CONSTRAINT UC_PCPROCESS_HASHVALUE UNIQUE (HASHVALUE)
)
END
GO

------------------------------ Transfer indexes -------------------------
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[pcprocess]') AND name = N'idx_T_hashvalue'
)
BEGIN
CREATE index idx_T_hashvalue on APM.pcprocess(hashvalue) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PCPROCESS]') AND name = N'idx_PCProcessId'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_PCProcessId] ON [APM].[PCPROCESS]
(
[PCPROCESSID]
)
INCLUDE
(
[EXTRAINFO],
[PROCESS]
)
WITH (SORT_IN_TEMPDB = OFF)
END
GO

EXEC DomainTableRegisterIndexOptimization
@TableName = 'PCPROCESS'
,@SchemaName = 'APM'
,@DatasetId = '$Config/DatasetId$'
GO

/*==============================================================*/
/* Table: PCTYPE */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.PCTYPE'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.PCTYPE (
PCTYPEID int identity,
TYPE nvarchar(255) NOT NULL,
MEASURE nvarchar(50) NULL,
INSTANCEFUNCTION nvarchar(50) NULL,
DATEFUNCTION nvarchar(50) NULL,
CONSTRAINT PK_PCTYPE primary key (PCTYPEID),
CONSTRAINT UC_PCTYPE_TYPE UNIQUE (TYPE)
)
END
GO

/*==============================================================*/
/* Index: IX_TYPE */
/*==============================================================*/
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PCTYPE]') AND name = N'IX_TYPE'
)
BEGIN
create unique index IX_TYPE on APM.PCTYPE (
TYPE ASC
)
END
GO

/*==============================================================*/
/* Table: PERFDAILY */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.PERFDAILY'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.PERFDAILY (
PERFDAILYID bigint identity,
PCTYPEID int not null,
MACHINEID int not null,
SOURCEID int null,
PCPROCESSID int null,
IS_STATE int null,
UTCDATE datetime not null,
SUMVALUE decimal(18,4) not null,
AVERAGEVALUE decimal(18,4) not null,
SAMPLECOUNT int not null,
MINVALUE decimal(18,4) not null,
MAXVALUE decimal(18,4) not null,
PACKAGECOUNTER int not null
)
END
GO

/*==============================================================*/
/* Index: IX_CDATE */
/*==============================================================*/

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PerfDaily]') AND name = N'IX_CDATE'
)
BEGIN
CREATE CLUSTERED INDEX IX_CDATE ON APM.PerfDaily
(
UTCDATE ASC
)
END
GO

IF NOT EXISTS
(
SELECT * FROM INFORMATION_SCHEMA.table_constraints WHERE TABLE_NAME = N'PERFDAILY' AND TABLE_SCHEMA = N'apm' AND CONSTRAINT_NAME=N'PK_PERFDAILY'
)
BEGIN
ALTER TABLE APM.PERFDAILY ADD CONSTRAINT PK_PERFDAILY PRIMARY KEY (PERFDAILYID)
END
GO

/*==============================================================*/
/* Index: FK_PERFDAILYMACHINEID */
/*==============================================================*/

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PERFDAILY]') AND name = N'FK_PERFDAILYMACHINEID'
)
BEGIN
create index FK_PERFDAILYMACHINEID on APM.PERFDAILY (
MACHINEID ASC
)
END
GO

/*==============================================================*/
/* Index: FK_PERFDAILYSOURCEID */
/*==============================================================*/

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PERFDAILY]') AND name = N'FK_PERFDAILYSOURCEID'
)
BEGIN
create index FK_PERFDAILYSOURCEID on APM.PERFDAILY (
SOURCEID ASC
)
END
GO

/*==============================================================*/
/* Index: FK_PERFDAILYPROCESSID */
/*==============================================================*/

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PERFDAILY]') AND name = N'FK_PERFDAILYPROCESSID'
)
BEGIN
create index FK_PERFDAILYPROCESSID on APM.PERFDAILY (
PCPROCESSID ASC
)
END
GO

/*==============================================================*/
/* Index: FK_PERFDAILYTYPEID */
/*==============================================================*/
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PERFDAILY]') AND name = N'FK_PERFDAILYTYPEID'
)
BEGIN
create index FK_PERFDAILYTYPEID on APM.PERFDAILY (
PCTYPEID ASC
)
END
GO

EXEC DomainTableRegisterIndexOptimization
@TableName = 'PERFDAILY'
,@SchemaName = 'APM'
,@DatasetId = '$Config/DatasetId$'
GO

/*==============================================================*/
/* Table: PERFHOURLY */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.PERFHOURLY'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.PERFHOURLY (
PERFHOURLYID bigint identity,
PCTYPEID int not null,
MACHINEID int not null,
SOURCEID int null,
PCPROCESSID int null,
IS_STATE int null,
UTCDATE datetime not null,
AVERAGEVALUE float(53) not null,
MINVALUE float(53) not null,
MAXVALUE float(53) not null,
SAMPLECOUNT bigint not null,
SUMVALUE float(53) not null,
PACKAGECOUNTER bigint not null,
HASHVALUE nvarchar(50) null
)
END
GO

/*==============================================================*/
/* Index: IX_CDATE */
/*==============================================================*/

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PERFHOURLY]') AND name = N'IX_CDATE'
)
BEGIN
CREATE CLUSTERED INDEX IX_CDATE ON APM.PERFHOURLY
(
UTCDATE ASC
)
END
GO

IF NOT EXISTS
(
SELECT * FROM INFORMATION_SCHEMA.table_constraints WHERE TABLE_NAME = N'PERFHOURLY' AND TABLE_SCHEMA = N'apm' AND CONSTRAINT_NAME=N'PK_PERFHOURLY'
)
BEGIN
ALTER TABLE APM.PERFHOURLY ADD CONSTRAINT PK_PERFHOURLY PRIMARY KEY (PERFHOURLYID)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PERFHOURLY]') AND name = N'IX_AGGREGATE'
)
BEGIN
CREATE NONCLUSTERED INDEX IX_AGGREGATE ON APM.PERFHOURLY
(
[PCTYPEID] ASC,
[MACHINEID] ASC,
[SOURCEID] ASC,
[PCPROCESSID] ASC,
[IS_STATE] ASC,
[UTCDATE] ASC,
[SUMVALUE] ASC
)
END
GO

--------------------- Summary Performance &amp; Summary Failure &amp; Problem Distribution ----------------------
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PERFHOURLY]') AND name = N'idx_TypeSourceMachineDate'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_TypeSourceMachineDate] ON [APM].[PERFHOURLY]
(
[PCTYPEID] ASC,
[SOURCEID] ASC,
[MACHINEID] ASC,
[UTCDATE] ASC
)
INCLUDE ([SUMVALUE], [MAXVALUE], [SAMPLECOUNT], [PACKAGECOUNTER], [PCPROCESSID])
WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PERFHOURLY]') AND name = N'idx_DateTypeSourceMachine'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_DateTypeSourceMachine] ON [APM].[PERFHOURLY]
(
[UTCDATE] ASC,
[PCTYPEID] ASC,
[SOURCEID] ASC,
[MACHINEID] ASC
)
INCLUDE ([SUMVALUE], [MAXVALUE], [SAMPLECOUNT], [PACKAGECOUNTER], [PCPROCESSID])
WITH (SORT_IN_TEMPDB = ON)
END
GO


IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PERFHOURLY]') AND name = N'idx_MachineSourceDateType'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_MachineSourceDateType] ON [APM].[PERFHOURLY]
(
[MACHINEID] ASC,
[SOURCEID] ASC,
[UTCDATE] ASC,
[PCTYPEID] ASC
)
INCLUDE ( [SAMPLECOUNT],
[SUMVALUE],
[MAXVALUE],
[PACKAGECOUNTER],
[PCPROCESSID]) WITH (SORT_IN_TEMPDB = ON)
END
GO


IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PERFHOURLY]') AND name = N'idx_SourceMachineDateType'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_SourceMachineDateType] ON [APM].[PERFHOURLY]
(
[SOURCEID] ASC,
[MACHINEID] ASC,
[UTCDATE] ASC,
[PCTYPEID] ASC
)
INCLUDE ( [SAMPLECOUNT],
[SUMVALUE],
[MAXVALUE],
[PACKAGECOUNTER],
[PCPROCESSID])
WITH (SORT_IN_TEMPDB = ON)
END
GO


IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PERFHOURLY]') AND name = N'idx_TypeDateSourceMachine'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_TypeDateSourceMachine] ON [APM].[PERFHOURLY]
(
[PCTYPEID] ASC,
[UTCDATE] ASC,
[SOURCEID] ASC,
[MACHINEID] ASC
)
INCLUDE ( [SAMPLECOUNT],
[SUMVALUE],
[MAXVALUE],
[PACKAGECOUNTER],
[PCPROCESSID])
WITH (SORT_IN_TEMPDB = ON)
END
GO

--------------------- Application Status -------------------------

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PERFHOURLY]') AND name = N'idx_SourceId'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_SourceId] ON [APM].[PERFHOURLY]
(
[SOURCEID] ASC
)
INCLUDE ([PCPROCESSID])
WITH (SORT_IN_TEMPDB = ON)
END
GO


IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PERFHOURLY]') AND name = N'idx_ProcessId'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_ProcessId] ON [APM].[PERFHOURLY]
(
[PCPROCESSID]ASC
)
INCLUDE ([SOURCEID])
WITH (SORT_IN_TEMPDB = ON)
END
GO


IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PERFHOURLY]') AND name = N'idx_SourceProcessMachine'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_SourceProcessMachine] ON [APM].[PERFHOURLY]
(
[SOURCEID] ASC,
[PCPROCESSID] ASC,
[MACHINEID] ASC
)
WITH (SORT_IN_TEMPDB = ON)
END
GO


IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PERFHOURLY]') AND name = N'idx_ProcessSourceMachine'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_ProcessSourceMachine] ON [APM].[PERFHOURLY]
(
[PCPROCESSID] ASC,
[SOURCEID] ASC,
[MACHINEID] ASC
)
WITH (SORT_IN_TEMPDB = ON)
END
GO


IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PERFHOURLY]') AND name = N'idx_MachineProcessSource'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_MachineProcessSource] ON [APM].[PERFHOURLY]
(
[MACHINEID] ASC,
[PCPROCESSID] ASC,
[SOURCEID] ASC
)
WITH (SORT_IN_TEMPDB = ON)
END
GO

--------------------- Transfer indexes -----------------------------

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PERFHOURLY]') AND name = N'idx_T_hashvalue'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_T_hashvalue] ON [APM].[PERFHOURLY]
(
[HASHVALUE] ASC
)
INCLUDE (
[MINVALUE],
[MAXVALUE],
[SAMPLECOUNT],
[SUMVALUE],
[PACKAGECOUNTER])
WITH (SORT_IN_TEMPDB = ON)
END
GO


/*==============================================================*/
/* Index: FK_PERFHOURLYMACHINEID */
/*==============================================================*/

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PERFHOURLY]') AND name = N'FK_PERFHOURLYMACHINEID'
)
BEGIN
CREATE INDEX FK_PERFHOURLYMACHINEID on APM.PERFHOURLY (
MACHINEID ASC
)
END
GO

/*==============================================================*/
/* Index: FK_PERFHOURLYSOURCEID */
/*==============================================================*/

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PERFHOURLY]') AND name = N'FK_PERFHOURLYSOURCEID'
)
BEGIN
create index FK_PERFHOURLYSOURCEID on APM.PERFHOURLY (
SOURCEID ASC
)
END
GO

/*==============================================================*/
/* Index: FK_PERFHOURLYPCTYPEID */
/*==============================================================*/
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PERFHOURLY]') AND name = N'FK_PERFHOURLYPCTYPEID'
)
BEGIN
CREATE INDEX FK_PERFHOURLYPCTYPEID on APM.PERFHOURLY (
PCTYPEID ASC
)
END
GO

/*==============================================================*/
/* Index: FK_PERFHOURLYPCPROCESSID */
/*==============================================================*/
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PERFHOURLY]') AND name = N'FK_PERFHOURLYPCPROCESSID'
)
BEGIN
CREATE INDEX FK_PERFHOURLYPCPROCESSID on APM.PERFHOURLY (
PCPROCESSID ASC
)
END
GO

EXEC DomainTableRegisterIndexOptimization
@TableName = 'PERFHOURLY'
,@SchemaName = 'APM'
,@DatasetId = '$Config/DatasetId$'
GO

/*==============================================================*/
/* Table: PERFORMANCENODE */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.PERFORMANCENODE'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.PERFORMANCENODE (
PERFORMANCENODEID bigint identity,
EVENTID bigint not null,
RESOURCEID int null,
RESOURCEGROUPNODEID int null,
DESCRIPTION nvarchar(255) null,
FUNCTIONNAME nvarchar(255) null,
RESOURCEMETHOD nvarchar(255) null,
DURATION decimal(35) not null,
HASHCODE nvarchar(255) null,
ENTRYID int not null,
SELFDURATION decimal(35) null,
ROWGUID nvarchar(15) null,
ISHEAVIESTNODE bit not null,
constraint PK_PERFORMANCENODE primary key (PERFORMANCENODEID)
)
END
GO

IF NOT EXISTS (
SELECT * FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME = 'PERFORMANCENODE' AND TABLE_SCHEMA = N'apm' AND COLUMN_NAME = 'IsHeaviestNode' AND COLUMN_DEFAULT IS NOT NULL
)
BEGIN
ALTER TABLE APM.PERFORMANCENODE ADD CONSTRAINT DF_PERFORMANCENODE_ISHAVIESTNODE DEFAULT 0 FOR IsHeaviestNode
END
GO

------------------------ Application Performance index-----------
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PERFORMANCENODE]') AND name = N'idx_EventIdResourceIdSelfDuration1'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_EventIdResourceIdSelfDuration1] ON [APM].[PERFORMANCENODE]
(
[EVENTID] ASC,
[RESOURCEID] ASC,
[SELFDURATION] ASC
)
INCLUDE ( [RESOURCEMETHOD]) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PERFORMANCENODE]') AND name = N'idx_EventIdResourceIdDuration'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_EventIdResourceIdDuration] ON [APM].[PERFORMANCENODE]
(
[EVENTID] ASC,
[RESOURCEID] ASC,
[DURATION] ASC
)
INCLUDE ( [RESOURCEMETHOD]) WITH (SORT_IN_TEMPDB = ON)
END
GO

------------------------ Transfer indexes ------------------------------
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[performancenode]') AND name = N'idx_T_eventIdResourceId'
)
BEGIN
CREATE INDEX idx_T_eventIdResourceId on APM.performancenode(eventid, resourceid)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[performanceNode]') AND name = N'idx_T_EventIdEntryId'
)
BEGIN
CREATE INDEX idx_T_EventIdEntryId on APM.performanceNode(EventId, EntryId) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PERFORMANCENODE]') AND name = N'idx_T_EventId'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_T_EventId] ON [APM].[PERFORMANCENODE]
(
[EVENTID]
)
INCLUDE ( [PerformanceNodeId],[RESOURCEMETHOD], ResourceGroupNodeId, [EntryId], [RESOURCEID], [SELFDURATION])
WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[performancenode]') AND name = N'idx_T_RowGuid'
)
BEGIN
CREATE INDEX idx_T_RowGuid on APM.performancenode(rowguid)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PERFORMANCENODE]') AND name = N'idx_T_ResourceIdEventId'
)
BEGIN
CREATE INDEX idx_T_ResourceIdEventId ON APM.PERFORMANCENODE
(
RESOURCEID,
EVENTID
) WITH (SORT_IN_TEMPDB = ON)
END
GO

----------------------- Event Window Indexes ----------------------
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PerformanceNode]') AND name = N'idx_W_EventIdResourceIdSelfDuration2'
)
BEGIN
CREATE INDEX idx_W_EventIdResourceIdSelfDuration2 on APM.PerformanceNode
(
EventId, ResourceId, SelfDuration Desc
)
INCLUDE(
[Description],
[DURATION],
[ENTRYID]
) WITH (SORT_IN_TEMPDB = ON)
END
GO

/*==============================================================*/
/* Index: FK_PERFORMANCENODERESOURCEID */
/*==============================================================*/
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PERFORMANCENODE]') AND name = N'FK_PERFORMANCENODERESOURCEID'
)
BEGIN
create index FK_PERFORMANCENODERESOURCEID on APM.PERFORMANCENODE (
RESOURCEID ASC
)
END
GO

/*==============================================================*/
/* Index: FK_PERFORMANCENODERESOURCEGROUPID */
/*==============================================================*/
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PERFORMANCENODE]') AND name = N'FK_PERFORMANCENODERESOURCEGROUPID'
)
BEGIN
create index FK_PERFORMANCENODERESOURCEGROUPID on APM.PERFORMANCENODE (
RESOURCEGROUPNODEID ASC
)
END
GO

/*==============================================================*/
/* Index: FK_PERFORMANCENODEEVENTID */
/*==============================================================*/
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PERFORMANCENODE]') AND name = N'FK_PERFORMANCENODEEVENTID'
)
BEGIN
create index FK_PERFORMANCENODEEVENTID on APM.PERFORMANCENODE (
EVENTID ASC
)
END
GO

/*==============================================================*/
/* Index: FK_PERFORMANCENODEVENTIDRESOURCEID */
/*==============================================================*/
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[PERFORMANCENODE]') AND name = N'FK_PERFORMANCENODEVENTIDRESOURCEID'
)
BEGIN
CREATE INDEX FK_PERFORMANCENODEVENTIDRESOURCEID on APM.PERFORMANCENODE (
EVENTID ASC,
RESOURCEID ASC
)
END
GO

EXEC DomainTableRegisterIndexOptimization
@TableName = 'PERFORMANCENODE'
,@SchemaName = 'APM'
,@DatasetId = '$Config/DatasetId$'
GO

/*==============================================================*/
/* Table: RELATIVEDATES */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.RELATIVEDATES'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.RELATIVEDATES (
ID int not null,
NAME nvarchar(255) not null,
ORDERBY int not null
)

INSERT INTO APM.RELATIVEDATES VALUES(0, '', 0)

INSERT INTO APM.RelativeDates([Id], [Name], [OrderBy])
SELECT 10, 'This Week: First Day', 6
UNION ALL
SELECT 20, 'This Week: Last Day', 7
UNION ALL
SELECT 30, 'Previous Week: First Day', 10
UNION ALL
SELECT 40, 'Previous Week: Last Day', 11
UNION ALL
SELECT 50, 'This Month: First Day', 4
UNION ALL
SELECT 60, 'This Month: Last Day', 5
UNION ALL
SELECT 70, 'Previous Month: First Day', 8
UNION ALL
SELECT 80, 'Previous Month: Last Day', 9
UNION ALL
SELECT 90, 'Today', 1
UNION ALL
SELECT 100, 'Yesterday', 2
END
GO


/*==============================================================*/
/* Table: RESOURCE */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.RESOURCE'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.RESOURCE (
RESOURCEID int identity,
RESOURCEGROUPID int not null,
SOURCEID int not null,
RESOURCEURIFORMAT nvarchar(255) not null,
RESOURCEURI nvarchar(255) not null,
constraint PK_RESOURCE primary key (RESOURCEID)
)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[RESOURCE]') AND name = N'idx_GroupResourceUri'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_GroupResourceUri] ON [APM].[RESOURCE]
(
[RESOURCEGROUPID] ASC,
[RESOURCEID] ASC,
[RESOURCEURI] ASC
)WITH (SORT_IN_TEMPDB = ON)
END
GO

------------------------ Transfer indexes -----------------------
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[RESOURCE]') AND name = N'idx_T_SourceResourceUri'
)
BEGIN
CREATE INDEX idx_T_SourceResourceUri ON APM.RESOURCE(sourceId, resourceUri)
include(resourceid, resourcegroupid) WITH (SORT_IN_TEMPDB = ON)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[RESOURCE]') AND name = N'idx_T_ResGroupUri'
)
BEGIN
CREATE INDEX idx_T_ResGroupUri ON APM.RESOURCE(ResourceGroupId, ResourceUri) include (sourceId, resourceid)
WITH (SORT_IN_TEMPDB = ON)
END
GO

------------------------ Event WINDOW indexes -----------------------
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[RESOURCE]') AND name = N'idx_W_ResourceUri'
)
BEGIN
CREATE INDEX idx_W_ResourceUri ON APM.RESOURCE (ResourceUri) INCLUDE(ResourceGroupId) WITH (SORT_IN_TEMPDB = ON)
END
GO

/*==============================================================*/
/* Index: FK_RESOURCERESOURCEGROUPID */
/*==============================================================*/
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[RESOURCE]') AND name = N'FK_RESOURCERESOURCEGROUPID'
)
BEGIN
create index FK_RESOURCERESOURCEGROUPID on APM.RESOURCE (
RESOURCEGROUPID ASC
)
END
GO

/*==============================================================*/
/* Index: FK_RESOURCESOURCEID */
/*==============================================================*/
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[RESOURCE]') AND name = N'FK_RESOURCESOURCEID'
)
BEGIN
CREATE INDEX FK_RESOURCESOURCEID on APM.RESOURCE (
SOURCEID ASC
)
END
GO

EXEC DomainTableRegisterIndexOptimization
@TableName = 'RESOURCE'
,@SchemaName = 'APM'
,@DatasetId = '$Config/DatasetId$'
GO

/*==============================================================*/
/* Table: RESOURCEGROUP */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.RESOURCEGROUP'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.RESOURCEGROUP (
RESOURCEGROUPID int identity,
NAME nvarchar(255) not null,
constraint PK_RESOURCEGROUP primary key (RESOURCEGROUPID)
)
END
GO

/*==============================================================*/
/* Table: RESOURCEGROUPNODE */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.RESOURCEGROUPNODE'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.RESOURCEGROUPNODE (
RESOURCEGROUPNODEID int identity,
EVENTID bigint not null,
RESOURCEGROUPID int not null,
DURATION bigint not null,
CALLCOUNT int null,
constraint PK_RESOURCEGROUPNODE primary key (RESOURCEGROUPNODEID)
)
END
GO

---------------------- Application Performance index-----------
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[RESOURCEGROUPNODE]') AND name = N'idx_EventIdResourceGroupNodeIdResourceGroupId'
)
BEGIN
CREATE NONCLUSTERED INDEX [idx_EventIdResourceGroupNodeIdResourceGroupId] ON [APM].[RESOURCEGROUPNODE]
(
[EVENTID] ASC,
[RESOURCEGROUPNODEID] ASC,
[RESOURCEGROUPID] ASC
)
INCLUDE ( [DURATION]) WITH (SORT_IN_TEMPDB = ON)
END
GO

/*==============================================================*/
/* Index: FK_RESOURCEGROUPNODERESOURCEGROUPID */
/*==============================================================*/
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[RESOURCEGROUPNODE]') AND name = N'FK_RESOURCEGROUPNODERESOURCEGROUPID'
)
BEGIN
CREATE INDEX FK_RESOURCEGROUPNODERESOURCEGROUPID on APM.RESOURCEGROUPNODE (
RESOURCEGROUPID ASC
)
END
GO

/*==============================================================*/
/* Index: FK_RESOURCEGROUPNODEEVENTID */
/*==============================================================*/
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[RESOURCEGROUPNODE]') AND name = N'FK_RESOURCEGROUPNODEEVENTID'
)
BEGIN
CREATE INDEX FK_RESOURCEGROUPNODEEVENTID on APM.RESOURCEGROUPNODE (
EVENTID ASC
)
END
GO

EXEC DomainTableRegisterIndexOptimization
@TableName = 'RESOURCEGROUPNODE'
,@SchemaName = 'APM'
,@DatasetId = '$Config/DatasetId$'
GO

/*==============================================================*/
/* Table: SEVIEWERDB */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.SEVIEWERDB'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.SEVIEWERDB (
SEVIEWERDBID int identity,
DATABASEID uniqueidentifier not null,
ADDRESS nvarchar(max) null,
constraint PK_SEVIEWERDB primary key (SEVIEWERDBID)
)
END
GO

IF NOT EXISTS
(
SELECT * FROM INFORMATION_SCHEMA.table_constraints WHERE TABLE_NAME = N'SEVIEWERDB' AND TABLE_SCHEMA = N'apm' AND CONSTRAINT_NAME=N'database_id_uniq'
)
BEGIN
ALTER TABLE APM.SEVIEWERDB add constraint database_id_uniq unique(databaseId)
END
GO

/*==============================================================*/
/* Table: SOURCE */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.SOURCE'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.SOURCE (
SOURCEID int identity,
SOURCE nvarchar(255) NOT NULL,
CONSTRAINT PK_SOURCE primary key (SOURCEID),
CONSTRAINT UC_SOURCE_SOURCE UNIQUE (SOURCE)
)
END
GO

/*==============================================================*/
/* Index: IX_SOURCE */
/*==============================================================*/
IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[SOURCE]') AND name = N'IX_SOURCE'
)
BEGIN
create unique index IX_SOURCE on APM.SOURCE (
SOURCE ASC
)
END
GO

/*==============================================================*/
/* Table: TASKS */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.TASKS'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.TASKS (
TASKID int identity,
TABLENAME nvarchar(50) not null,
STARTDATE datetime null,
ENDDATE datetime null,
OPERATIONID int not null,
LASTTIMESTAMP bigint null,
STATUS nvarchar(50) null,
SEVIEWERDBID int null,
constraint PK_TASKS primary key (TASKID)
)
END
GO

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[TASKS]') AND name = N'idx_T_TableNameDatabase'
)
BEGIN
CREATE INDEX idx_T_TableNameDatabase ON APM.TASKS
(tablename, seviewerdbid) INCLUDE(lasttimestamp)
END
GO

EXEC DomainTableRegisterIndexOptimization
@TableName = 'TASKS'
,@SchemaName = 'APM'
,@DatasetId = '$Config/DatasetId$'
GO

/*==============================================================*/
/* Table: TIMEZONE */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.TIMEZONE'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.TIMEZONE (
NAME nvarchar(255) null,
OFFSET int null
)

INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT-12:00', -720)
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT-11:00', -660)
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT-10:00', -600)
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT-9:00', -540)
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT-8:00', -480)
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT-7:00', -420)
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT-6:00', -360)
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT-5:00', -300)
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT-4:00', -240)
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT-3:30', -210)
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT-3:00', -180)
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT-2:00', -120)
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT-1:00', -60)
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT-0:00', 0)
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT+1:00', 60)
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT+2:00', 120)
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT+3:00', 180)
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT+3:30', 210)
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT+4:00', 240)
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT+4:30', 270)
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT+5:00', 300)
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT+5:30', 330)
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT+5:45', 345)
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT+6:00', 360)
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT+6:30', 390)
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT+7:00', 420)
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT+8:00', 480)
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT+9:00', 540)
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT+9:30', 570)
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT+10:00', 600)
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT+11:00', 660)
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT+12:00', 720)
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT+13:00', 780)

/* Daylight Saving time zones*/
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT-2:30', -150)
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT+6:45', 405)
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT+10:30', 630)
INSERT INTO APM.TIMEZONE (NAME, OFFSET) VALUES ('GMT+14:00', 840)
END
GO

/*==============================================================*/
/* Table: USERS */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.USERS'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE APM.USERS (
USERID int identity,
NAME nvarchar(255) not null,
constraint PK_USERS primary key (USERID)
)
END
GO

IF NOT EXISTS
(
SELECT * FROM INFORMATION_SCHEMA.table_constraints WHERE TABLE_NAME = N'Users' AND TABLE_SCHEMA = N'apm' AND CONSTRAINT_NAME=N'Name_Unique'
)
BEGIN
ALTER TABLE [APM].[Users] ADD CONSTRAINT Name_Unique UNIQUE (NAME)
END
GO

/*==============================================================*/
/* Table: EVENTDETAIL */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.EVENTDETAIL'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE [APM].[EVENTDETAIL](
[EVENTDETAILID] [int] IDENTITY(1,1) NOT NULL,
[EVENTID] [bigint] NULL,
[NAME] [nvarchar](50) NULL,
[VALUE] [nvarchar](255) NULL,
[VALUETYPE] [nvarchar](50) NULL
CONSTRAINT [PK_EVENTDETAIL] PRIMARY KEY CLUSTERED
(
[EVENTDETAILID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
END
GO

/****** Object: Index [IX_EVENTID] ******/

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[EVENTDETAIL]') AND name = N'IX_EVENTID'
)
BEGIN
CREATE NONCLUSTERED INDEX [IX_EVENTID] ON [APM].[EVENTDETAIL]
(
[EVENTID] ASC
)WITH (MAXDOP = 1, SORT_IN_TEMPDB = ON, ONLINE = OFF) ON [PRIMARY]
END
GO

EXEC DomainTableRegisterIndexOptimization
@TableName = 'EVENTDETAIL'
,@SchemaName = 'APM'
,@DatasetId = '$Config/DatasetId$'
GO

/*==============================================================*/
/* Table: CSEVENTDETAIL */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.CSEVENTDETAIL'), 'IsTable') IS NULL)
BEGIN
CREATE TABLE [APM].[CSEVENTDETAIL](
[CSEVENTDETAILID] [int] IDENTITY(1,1) NOT NULL,
[CSEVENTID] [int] NULL,
[NAME] [nvarchar](50) NULL,
[VALUE] [nvarchar](255) NULL,
[VALUETYPE] [nvarchar](50) NULL
CONSTRAINT [PK_CSEVENTDETAIL] PRIMARY KEY CLUSTERED
(
[CSEVENTDETAILID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]
END
GO

/****** Object: Index [[IX_CSEVENTID]] ******/

IF NOT EXISTS
(
SELECT * FROM sys.indexes WHERE object_id = OBJECT_ID(N'[apm].[CSEVENTDETAIL]') AND name = N'IX_CSEVENTID'
)
BEGIN
CREATE NONCLUSTERED INDEX [IX_CSEVENTID] ON [APM].[CSEVENTDETAIL]
(
[CSEVENTID] ASC
)WITH (MAXDOP = 1, SORT_IN_TEMPDB = ON, ONLINE = OFF) ON [PRIMARY]
END
GO

EXEC DomainTableRegisterIndexOptimization
@TableName = 'CSEVENTDETAIL'
,@SchemaName = 'APM'
,@DatasetId = '$Config/DatasetId$'
GO

/*==============================================================*/
/* View: V_APPLICATIONSOURCEMACHINE */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.V_APPLICATIONSOURCEMACHINE'), 'IsView') IS NULL)
BEGIN
EXECUTE('CREATE VIEW APM.V_APPLICATIONSOURCEMACHINE
AS
select clmn=1')
END
GO

ALTER VIEW APM.V_APPLICATIONSOURCEMACHINE as
SELECT A.APPLICATIONID, B.SOURCEID, M.MACHINEID, A.APPLICATION, B.SOURCE, M.MACHINE AS MACHINENAME
FROM APM.APPLICATION A
INNER JOIN APM.APPLICATIONSOURCEMACHINE C ON A.APPLICATIONID = C.APPLICATIONID
LEFT JOIN APM.SOURCE B ON B.SOURCEID = C.SOURCEID
LEFT JOIN APM.MACHINE M ON M.MACHINEID = C.MACHINEID
GO

/*==============================================================*/
/* View: V_EVENTWINDOW */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.V_EVENTWINDOW'), 'IsView') IS NULL) BEGIN
EXECUTE('CREATE VIEW APM.V_EVENTWINDOW
AS
select clmn=1')
END
GO

ALTER VIEW APM.V_EVENTWINDOW as
SELECT E.EVENTID, E.EVENTGROUPID, E.CATEGORY, E.DESCRIPTION, E.EVENTDURATION, E.ROOTNODENAME,
E.UTCEVENTDATE, E.EVENTCLASSTYPE, E.ASPECT,E.EXCEPTIONCLASS, E.RESOURCEID, E.ROWGUID, E.HEAVYLIGHT,E.SEVIEWEREGID,
S.SOURCE, S.SOURCEID, M.MACHINE, M.MACHINEID, SDB.ADDRESS AS PATH,
E.USERID,USR.NAME AS USERNAME, E.PMSTATUS
FROM APM.EVENT (NOLOCK) AS E INNER JOIN APM.SOURCE AS S ON S.SOURCEID=E.SOURCEID
INNER JOIN APM.MACHINE (NOLOCK) AS M ON M.MACHINEID=E.MACHINEID
INNER JOIN APM.SEVIEWERDB (NOLOCK) AS SDB ON SDB.SEVIEWERDBID=E.SEVIEWERDBID
LEFT JOIN APM.USERS (NOLOCK) AS USR ON E.USERID=USR.USERID
GO

/* foreign key to trace */
if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_PMSERVEREVENTTRACE_PMTRACE')
BEGIN
ALTER TABLE APM.PMSERVEREVENTTRACE ADD CONSTRAINT FK_PMSERVEREVENTTRACE_PMTRACE FOREIGN KEY (PMTRACEID) REFERENCES APM.PMTRACE(PMTRACEID)
END
GO

/* foreign key to event delete cascade */
if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_PMSERVEREVENTTRACE_PMEVENT')
BEGIN
ALTER TABLE APM.PMSERVEREVENTTRACE ADD CONSTRAINT FK_PMSERVEREVENTTRACE_PMEVENT FOREIGN KEY (EVENTID) REFERENCES APM.EVENT(EVENTID) ON DELETE CASCADE
END
GO

GO
/* foreign key to trace */
if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_PMCLIENTEVENTTRACE_PMTRACE')
BEGIN
ALTER TABLE APM.PMCLIENTEVENTTRACE ADD CONSTRAINT FK_PMCLIENTEVENTTRACE_PMTRACE FOREIGN KEY (PMTRACEID) REFERENCES APM.PMTRACE(PMTRACEID)
END
GO

/* foreign key to csevent delete cascade */
if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_PMCLIENTEVENTTRACE_PMEVENT')
BEGIN
ALTER TABLE APM.PMCLIENTEVENTTRACE ADD CONSTRAINT FK_PMCLIENTEVENTTRACE_PMEVENT FOREIGN KEY (CSEVENTID) REFERENCES APM.CSEVENT(CSEVENTID) ON DELETE CASCADE
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_EVENTDET_REFERENCE_EVENT')
BEGIN
ALTER TABLE [APM].[EVENTDETAIL] WITH CHECK ADD CONSTRAINT [FK_EVENTDET_REFERENCE_EVENT] FOREIGN KEY([EVENTID])
REFERENCES [APM].[EVENT] ([EVENTID])
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_CSEVENTDET_REFERENCE_CSEVENT')
BEGIN
ALTER TABLE [APM].[CSEVENTDETAIL] WITH CHECK ADD CONSTRAINT [FK_CSEVENTDET_REFERENCE_CSEVENT] FOREIGN KEY([CSEVENTID])
REFERENCES [APM].[CSEVENT] ([CSEVENTID])
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_APPLICAT_FK_APPLIC_APPLICAT')
BEGIN
alter table APM.APPLICATIONSOURCEMACHINE
add constraint FK_APPLICAT_FK_APPLIC_APPLICAT foreign key (APPLICATIONID)
references APM.APPLICATION (APPLICATIONID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_APPLICAT_FK_MACHIN_MACHINE')
BEGIN
alter table APM.APPLICATIONSOURCEMACHINE
add constraint FK_APPLICAT_FK_MACHIN_MACHINE foreign key (MACHINEID)
references APM.MACHINE (MACHINEID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_APPLICAT_FK_SOURCE_SOURCE')
BEGIN
alter table APM.APPLICATIONSOURCEMACHINE
add constraint FK_APPLICAT_FK_SOURCE_SOURCE foreign key (SOURCEID)
references APM.SOURCE (SOURCEID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_CSAJAX_REFERENCE_CSEVENT')
BEGIN
alter table APM.CSAJAX
add constraint FK_CSAJAX_REFERENCE_CSEVENT foreign key (CSEVENTID)
references APM.CSEVENT (CSEVENTID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_CSASYNCA_REFERENCE_CSEVENT')
BEGIN
alter table APM.CSASYNCAJAX
add constraint FK_CSASYNCA_REFERENCE_CSEVENT foreign key (CSEVENTID)
references APM.CSEVENT (CSEVENTID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_CSEVENT_REFERENCE_MACHINE')
BEGIN
alter table APM.CSEVENT
add constraint FK_CSEVENT_REFERENCE_MACHINE foreign key (MACHINEID)
references APM.MACHINE (MACHINEID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_CSEVENT_REFERENCE_SOURCE')
BEGIN
alter table APM.CSEVENT
add constraint FK_CSEVENT_REFERENCE_SOURCE foreign key (SOURCEID)
references APM.SOURCE (SOURCEID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_CSEVENT_REFERENCE_CSEVENTG')
BEGIN
alter table APM.CSEVENT
add constraint FK_CSEVENT_REFERENCE_CSEVENTG foreign key (CSEVENTGROUPID)
references APM.CSEVENTGROUP (CSEVENTGROUPID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_CSEVENT_REFERENCE_IP')
BEGIN
alter table APM.CSEVENT
add constraint FK_CSEVENT_REFERENCE_IP foreign key (IPID)
references APM.IP (IPID)
END
GO

IF NOT EXISTS
(
SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = N'FK_CSEVENT_USERS'
)
BEGIN
alter table APM.CSEVENT
add constraint FK_CSEVENT_USERS foreign key (USERID)
references APM.USERS (USERID)
END
GO

IF NOT EXISTS
(
SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = N'FK_CSEXEVEN_REFERENCE_CSEVENT'
)
BEGIN
alter table APM.CSEXEVENT
add constraint FK_CSEXEVEN_REFERENCE_CSEVENT foreign key (CSEVENTID)
references APM.CSEVENT (CSEVENTID)
END
GO

IF NOT EXISTS
(
SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = N'FK_CSHEAVIE_REFERENCE_CSEVENT'
)
BEGIN
alter table APM.CSHEAVIESTRESOURCE
add constraint FK_CSHEAVIE_REFERENCE_CSEVENT foreign key (CSEVENTID)
references APM.CSEVENT (CSEVENTID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_CSJSCRIP_REFERENCE_CSEVENT')
BEGIN
alter table APM.CSJSCRIPTEVENT
add constraint FK_CSJSCRIP_REFERENCE_CSEVENT foreign key (CSEVENTID)
references APM.CSEVENT (CSEVENTID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_CSPAGEEV_REFERENCE_CSEVENT')
BEGIN
alter table APM.CSPAGEEVENT
add constraint FK_CSPAGEEV_REFERENCE_CSEVENT foreign key (CSEVENTID)
references APM.CSEVENT (CSEVENTID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_CSPERIPH_REFERENCE_CSEVENT')
BEGIN
alter table APM.CSPERIPHERAL
add constraint FK_CSPERIPH_REFERENCE_CSEVENT foreign key (CSEVENTID)
references APM.CSEVENT (CSEVENTID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_CSPERIPH_REFERENCE_CSPERIPH')
BEGIN
alter table APM.CSPERIPHERALDETAIL
add constraint FK_CSPERIPH_REFERENCE_CSPERIPH foreign key (CSPERIPHERALID)
references APM.CSPERIPHERAL (CSPERIPHERALID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_DATASET_AGGREGATION')
BEGIN
alter table APM.DATASET
add constraint FK_DATASET_AGGREGATION foreign key (AGGREGATIONTYPEID)
references APM.AGGREGATIONTYPE (AGGREGATIONTYPEID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_DATASET_HISTORY')
BEGIN
alter table APM.DATASETAGGREGATIONHISTORY
add constraint FK_DATASET_HISTORY foreign key (DATASETID)
references APM.DATASET (DATASETID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_EVENT_FK_EVENTG_EVENTGRO')
BEGIN
alter table APM.EVENT
add constraint FK_EVENT_FK_EVENTG_EVENTGRO foreign key (EVENTGROUPID)
references APM.EVENTGROUP (EVENTGROUPID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_EVENT_FK_EVENT__IP')
BEGIN
alter table APM.EVENT
add constraint FK_EVENT_FK_EVENT__IP foreign key (IPID)
references APM.IP (IPID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_EVENT_FK_EVENT__SEVIEWER')
BEGIN
alter table APM.EVENT
add constraint FK_EVENT_FK_EVENT__SEVIEWER foreign key (SEVIEWERDBID)
references APM.SEVIEWERDB (SEVIEWERDBID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_EVENT_FK_SOURCE_SOURCE')
BEGIN
alter table APM.EVENT
add constraint FK_EVENT_FK_SOURCE_SOURCE foreign key (SOURCEID)
references APM.SOURCE (SOURCEID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_EVENT_REFERENCE_MACHINE')
BEGIN
alter table APM.EVENT
add constraint FK_EVENT_REFERENCE_MACHINE foreign key (MACHINEID)
references APM.MACHINE (MACHINEID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_EVENT_REFERENCE_RESOURCE')
BEGIN
alter table APM.EVENT
add constraint FK_EVENT_REFERENCE_RESOURCE foreign key (RESOURCEID)
references APM.RESOURCE (RESOURCEID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_EVENT_USERS')
BEGIN
alter table APM.EVENT
add constraint FK_EVENT_USERS foreign key (USERID)
references APM.USERS (USERID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_EXCEPTIO_FK_EXCEPT_EVENT')
BEGIN
alter table APM.EXCEPTIONNODE
add constraint FK_EXCEPTIO_FK_EXCEPT_EVENT foreign key (EVENTID)
references APM.EVENT (EVENTID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_EXCEPTIO_REFERENCE_RESOURCE')
BEGIN
alter table APM.EXCEPTIONNODE
add constraint FK_EXCEPTIO_REFERENCE_RESOURCE foreign key (RESOURCEID)
references APM.RESOURCE (RESOURCEID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_MEMBERAP_FK_APPLIC_APPLICAT')
BEGIN
alter table APM.MEMBERAPPLICATION
add constraint FK_MEMBERAP_FK_APPLIC_APPLICAT foreign key (APPLICATIONID)
references APM.APPLICATION (APPLICATIONID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_MEMBERAP_FK_USER_MEMBER')
BEGIN
alter table APM.MEMBERAPPLICATION
add constraint FK_MEMBERAP_FK_USER_MEMBER foreign key (MEMBERID)
references APM.MEMBER (MEMBERID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_PERFDAYLY_TYPE')
BEGIN
alter table APM.PERFDAILY
add constraint FK_PERFDAYLY_TYPE foreign key (PCTYPEID)
references APM.PCTYPE (PCTYPEID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_PERFDAYLY_MACHINE')
BEGIN
alter table APM.PERFDAILY
add constraint FK_PERFDAYLY_MACHINE foreign key (MACHINEID)
references APM.MACHINE (MACHINEID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_PERFDAYLY_SOURCE')
BEGIN
alter table APM.PERFDAILY
add constraint FK_PERFDAYLY_SOURCE foreign key (SOURCEID)
references APM.SOURCE (SOURCEID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_PERFDAIL_REFERENCE_PCPROCES')
BEGIN
alter table APM.PERFDAILY
add constraint FK_PERFDAIL_REFERENCE_PCPROCES foreign key (PCPROCESSID)
references APM.PCPROCESS (PCPROCESSID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_PERFHOURLY_PCTYPE')
BEGIN
alter table APM.PERFHOURLY
add constraint FK_PERFHOURLY_PCTYPE foreign key (PCTYPEID)
references APM.PCTYPE (PCTYPEID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_PERFHOURLY_MACHINE')
BEGIN
alter table APM.PERFHOURLY
add constraint FK_PERFHOURLY_MACHINE foreign key (MACHINEID)
references APM.MACHINE (MACHINEID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_PERFHOURLY_SOURCE')
BEGIN
alter table APM.PERFHOURLY
add constraint FK_PERFHOURLY_SOURCE foreign key (SOURCEID)
references APM.SOURCE (SOURCEID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_PERFHOUR_REFERENCE_PCPROCES')
BEGIN
alter table APM.PERFHOURLY
add constraint FK_PERFHOUR_REFERENCE_PCPROCES foreign key (PCPROCESSID)
references APM.PCPROCESS (PCPROCESSID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_PERFORMANCENODE_EVENT')
BEGIN
alter table APM.PERFORMANCENODE
add constraint FK_PERFORMANCENODE_EVENT foreign key (EVENTID)
references APM.EVENT (EVENTID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_PERFORMA_REFERENCE_RESOURCEGROUP')
BEGIN
alter table APM.PERFORMANCENODE
add constraint FK_PERFORMA_REFERENCE_RESOURCEGROUP foreign key (RESOURCEGROUPNODEID)
references APM.RESOURCEGROUPNODE (RESOURCEGROUPNODEID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_PERFORMA_REFERENCE_RESOURCE')
BEGIN
alter table APM.PERFORMANCENODE
add constraint FK_PERFORMA_REFERENCE_RESOURCE foreign key (RESOURCEID)
references APM.RESOURCE (RESOURCEID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_RESOURCE_REFERENCE_RESOURCE')
BEGIN
alter table APM.RESOURCE
add constraint FK_RESOURCE_REFERENCE_RESOURCE foreign key (RESOURCEGROUPID)
references APM.RESOURCEGROUP (RESOURCEGROUPID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_RESOURCE_REFERENCE_SOURCE')
BEGIN
alter table APM.RESOURCE
add constraint FK_RESOURCE_REFERENCE_SOURCE foreign key (SOURCEID)
references APM.SOURCE (SOURCEID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_RESOURCE_REFERENCE_RESOURCENODE')
BEGIN
alter table APM.RESOURCEGROUPNODE
add constraint FK_RESOURCE_REFERENCE_RESOURCENODE foreign key (RESOURCEGROUPID)
references APM.RESOURCEGROUP (RESOURCEGROUPID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_RESOURCE_REFERENCE_EVENT')
BEGIN
alter table APM.RESOURCEGROUPNODE
add constraint FK_RESOURCE_REFERENCE_EVENT foreign key (EVENTID)
references APM.EVENT (EVENTID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_TASKS_TaskMode')
BEGIN
alter table APM.TASKS
add constraint FK_TASKS_TaskMode foreign key (OPERATIONID)
references APM.OPERATION (OPERATIONID)
END
GO

if NOT EXISTS (SELECT * FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS WHERE CONSTRAINT_NAME = 'FK_TASKS_REFERENCE_SEVIEWER')
BEGIN
alter table APM.TASKS
add constraint FK_TASKS_REFERENCE_SEVIEWER foreign key (SEVIEWERDBID)
references APM.SEVIEWERDB (SEVIEWERDBID)
END
GO

/*==============================================================*/
/* Common security reporting functions */
/*==============================================================*/
IF (OBJECTPROPERTY(OBJECT_ID('APM.FN_ADMINUSER'), 'IsScalarFunction') IS NULL)
BEGIN
EXECUTE('CREATE FUNCTION APM.FN_ADMINUSER ()
RETURNS int
AS begin return 1 end')
END
GO


/*==============================================================*/
/* Function: FN_ADMINUSER */
/*==============================================================*/
ALTER FUNCTION APM.FN_ADMINUSER(@USERNAME NVARCHAR(100))
RETURNS INT AS
BEGIN
DECLARE @A INT
SET @A = (SELECT MEMBERID FROM APM.MEMBER WHERE LOGINNAME = @USERNAME AND USERTYPE='a')
RETURN @A
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.FN_ISSECURE'), 'IsScalarFunction') IS NULL)
BEGIN
EXECUTE('CREATE FUNCTION APM.FN_ISSECURE ()
RETURNS int
AS begin return 1 end')
END
GO

/*==============================================================*/
/* Function: FN_ISSECURE */
/*==============================================================*/

ALTER FUNCTION APM.FN_ISSECURE ()
RETURNS INT AS
BEGIN
DECLARE @A INT
SELECT @A = CAST(CAST(CONFIGVALUE AS NCHAR) AS INT) FROM APM.CONFIG WHERE CONFIGNAME = 'SECURITYMODE'
RETURN @A
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.DATASETAGGREGATE'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.DATASETAGGREGATE AS RETURN 1')
END
GO
ALTER PROCEDURE APM.DATASETAGGREGATE
@DATASETNAME NVARCHAR(50)
,@DESCRIPTORS NTEXT
,@AGGREGATIONTARGETSTARTDATETIME DATETIME = NULL
,@INTERVALSTOAGGREGATE INT = NULL
,@RETURN BIT
AS
BEGIN
SET NOCOUNT ON

DECLARE
@DATASETID INT
,@AGGREGATIONINTERVALCOUNT INT
,@LASTMIDNIGHTDATETIME DATETIME
,@CURRENTAGGREGATIONSTARTDELAYMINUTES INT
,@CURRENTAGGREGATIONTYPEID TINYINT
,@CURRENTAGGREGATIONINTERVALDURATIONMINUTES INT
,@INTERVALSTARTDATETIME DATETIME
,@INTERVALENDDATETIME DATETIME
,@DATASETAGGREGATIONHISTORYID INT
,@I INT
,@AGGREGATIONSTARTDATETIME DATETIME
,@STATEMENT NVARCHAR(255)
,@UTCOFFSETMINUTES INT
,@MAXDATAAGEDAYS INT
,@MAXHISTORYDATE DATETIME

DECLARE
@ERROR INT

SET @UTCOFFSETMINUTES = DATEDIFF(MINUTE, GETDATE(), GETUTCDATE())

SELECT
@DATASETID = DATASETID,
@AGGREGATIONINTERVALCOUNT = ISNULL(@INTERVALSTOAGGREGATE, DEFAULTAGGREGATIONINTERVALCOUNT),
@CURRENTAGGREGATIONTYPEID = AGTYPE.AGGREGATIONTYPEID,
@CURRENTAGGREGATIONINTERVALDURATIONMINUTES = AGTYPE.AGGREGATIONINTERVALDURATIONMINUTES,
@CURRENTAGGREGATIONSTARTDELAYMINUTES = AGTYPE.AGGREGATIONSTARTDELAYMINUTES,
@STATEMENT = AGGREGATIONMETHODNAME
FROM APM.DATASET DATASET
JOIN APM.AGGREGATIONTYPE AGTYPE ON AGTYPE.AGGREGATIONTYPEID = DATASET.AGGREGATIONTYPEID
WHERE DATASET.DATASETNAME = @DATASETNAME

SET @ERROR = 0

IF (@AGGREGATIONINTERVALCOUNT &lt; 1)
SET @AGGREGATIONINTERVALCOUNT = 1

IF (@AGGREGATIONTARGETSTARTDATETIME IS NULL)
SET @AGGREGATIONTARGETSTARTDATETIME = GETUTCDATE()

-- FIND THE LAST AGGREGATION INTERVAL WHICH ENDED BEFORE
-- THE AGGREGATION START DATE TIME
IF (@CURRENTAGGREGATIONTYPEID &lt; 30)
BEGIN
--HOURLY AGGREGATION
SET @LASTMIDNIGHTDATETIME = CAST(CONVERT(CHAR(8), @AGGREGATIONTARGETSTARTDATETIME, 112) AS DATETIME)
SET @INTERVALSTARTDATETIME = DATEADD(
MINUTE
,ABS(DATEDIFF(MINUTE, @LASTMIDNIGHTDATETIME, @AGGREGATIONTARGETSTARTDATETIME)) / @CURRENTAGGREGATIONINTERVALDURATIONMINUTES * @CURRENTAGGREGATIONINTERVALDURATIONMINUTES - @CURRENTAGGREGATIONINTERVALDURATIONMINUTES
,CAST(CONVERT(CHAR(8), @AGGREGATIONTARGETSTARTDATETIME, 112) AS DATETIME))
END
ELSE IF (@CURRENTAGGREGATIONTYPEID = 30)
BEGIN
--DAILY AGGREGATION
-- SET @INTERVALSTARTDATETIME = DATEADD(MINUTE, @UTCOFFSETMINUTES, CAST(CONVERT(CHAR(8), GETDATE(), 112) AS DATETIME))
SET @INTERVALSTARTDATETIME = DATEADD(MINUTE, @UTCOFFSETMINUTES, CAST(CONVERT(CHAR(8), @AGGREGATIONTARGETSTARTDATETIME, 112) AS DATETIME))
END

SET @I = @AGGREGATIONINTERVALCOUNT

DECLARE @AGGREGATION TABLE
(
AGGREGATIONDATETIME DATETIME NOT NULL,
AGGREGATIONTYPEID BIT NOT NULL
)

WHILE (@I &gt; 0)
BEGIN
INSERT @AGGREGATION(AGGREGATIONDATETIME, AGGREGATIONTYPEID)
VALUES (@INTERVALSTARTDATETIME, @CURRENTAGGREGATIONTYPEID)

SET @I = @I - 1
SET @INTERVALSTARTDATETIME = DATEADD(MINUTE, -@CURRENTAGGREGATIONINTERVALDURATIONMINUTES, @INTERVALSTARTDATETIME)
END

-- GROOM AGGREGATION HISTORY
SELECT @MAXDATAAGEDAYS = ISNULL(MAXDATAAGEDAYS, 30)
FROM DATASET WHERE DATASETID = @DATASETID
SELECT @MAXHISTORYDATE = DATEADD(DD, -@MAXDATAAGEDAYS, ISNULL(MAX(AGGREGATIONDATETIME), GETUTCDATE()))
FROM DATASETAGGREGATIONHISTORY WHERE DIRTYIND = 0 AND DATASETID = @DATASETID

DELETE DATASETAGGREGATIONHISTORY
WHERE (AGGREGATIONDATETIME &lt; @MAXHISTORYDATE) AND (DIRTYIND = 0)

INSERT APM.DATASETAGGREGATIONHISTORY (
DATASETID
,AGGREGATIONDATETIME
)
SELECT
@DATASETID
,A.AGGREGATIONDATETIME
FROM @AGGREGATION A
WHERE NOT EXISTS (SELECT * FROM APM.DATASETAGGREGATIONHISTORY
WHERE (DATASETID = @DATASETID)
AND (AGGREGATIONDATETIME = A.AGGREGATIONDATETIME)
)


-- SELECT AGGREGATION PERIOD TO WORK ON
-- FIRST SELECT OLDEST NEVER AGGREGATED INTERVAL
-- IF NONE EXIST SELECT OLDEST DIRTY INTERVAL
SELECT TOP 1
@DATASETAGGREGATIONHISTORYID = DATASETAGGREGATIONHISTORYID
,@INTERVALSTARTDATETIME = AH.AGGREGATIONDATETIME
,@INTERVALENDDATETIME = DATEADD(MINUTE, @CURRENTAGGREGATIONINTERVALDURATIONMINUTES, AH.AGGREGATIONDATETIME)
FROM APM.DATASETAGGREGATIONHISTORY AH
WHERE (AH.DATASETID = @DATASETID)
AND (DATEADD(MINUTE, @CURRENTAGGREGATIONINTERVALDURATIONMINUTES + @CURRENTAGGREGATIONSTARTDELAYMINUTES, AH.AGGREGATIONDATETIME) &lt; GETUTCDATE()) -- AGGREGATION INTERVAL + SLIGHT DELAY IS IN THE PAST
AND (DIRTYIND = 1)
ORDER BY AH.AGGREGATIONDATETIME ASC

IF (@RETURN = 1)
BEGIN
CREATE TABLE #DATASETAGGREGATETABLE
(
UTCDATE DATETIME
,PCTYPEID INT
,MACHINEID INT
,SOURCEID INT
,PCPROCESSID INT
,IS_STATE INT
,AVERAGEVALUE DECIMAL(18, 4)
,SUMVALUE DECIMAL(18, 4)
,MINVALUE DECIMAL(18, 4)
,MAXVALUE DECIMAL(18, 4)
,SAMPLECOUNT INT
,PACKAGECOUNTER INT
)
SET @ERROR = @@ERROR

IF (@ERROR &lt;&gt; 0)
GOTO ERRORQUIT
END

IF (@DATASETAGGREGATIONHISTORYID IS NOT NULL)
BEGIN
DECLARE @SQL NVARCHAR(1000)
SET @SQL =
N'EXEC APM.' + QUOTENAME(@STATEMENT) +
'
@DESCRIPTORS
,@INTERVALSTARTDATETIME
,@INTERVALENDDATETIME
'
IF (@RETURN = 1)
SET @SQL = N'INSERT INTO #DATASETAGGREGATETABLE ' + @SQL

EXECUTE SP_EXECUTESQL @SQL, N'@DESCRIPTORS ntext, @INTERVALSTARTDATETIME datetime, @INTERVALENDDATETIME datetime',
@DESCRIPTORS,
@INTERVALSTARTDATETIME,
@INTERVALENDDATETIME

SET @ERROR = @@ERROR
IF (@ERROR = 0)
BEGIN
-- UPDATE AGGREGATION HISTORY
UPDATE DATASETAGGREGATIONHISTORY
SET DIRTYIND = 0
WHERE (DATASETID = @DATASETID)
AND (AGGREGATIONDATETIME = @INTERVALSTARTDATETIME)
END
END

IF (@RETURN = 1)
SELECT * FROM #DATASETAGGREGATETABLE

ERRORQUIT:
RETURN @ERROR
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.PCOUNTERAGGREGATE'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.PCOUNTERAGGREGATE AS RETURN 1')
END
GO
alter PROCEDURE APM.PCOUNTERAGGREGATE
@DESCRIPTORS NTEXT
,@INTERVALSTARTDATETIME DATETIME
,@INTERVALENDDATETIME DATETIME
AS
BEGIN
SET NOCOUNT ON

DECLARE @ERROR INT

SET @ERROR = 0

CREATE TABLE #PCOUNTERAGGREGATE_TMP (PCTYPEID INT, MACHINEID INT, PACKAGECOUNTER INT)

INSERT INTO #PCOUNTERAGGREGATE_TMP(PCTYPEID, MACHINEID, PACKAGECOUNTER)

SELECT
P.PCTYPEID,
P.MACHINEID,
COUNT(DISTINCT P.UTCDATE) PACKAGE_COUNT
FROM
PERFHOURLY P WITH (NOLOCK)
JOIN PCTYPE T WITH (NOLOCK) ON T.PCTYPEID = P.PCTYPEID AND
T.TYPE IN (
N'\Processor\% Processor Time',
N'\PROCESS\PRIVATE BYTES',
N'\PROCESS\IO DATA BYTES/SEC'
)
WHERE
(COALESCE(P.SUMVALUE, 0) &lt;&gt; 0)
AND (P.UTCDATE &gt;= @INTERVALSTARTDATETIME)
AND (P.UTCDATE &lt; @INTERVALENDDATETIME)
GROUP BY
P.PCTYPEID,
P.MACHINEID

INSERT PERFDAILY (
UTCDATE
,PCTYPEID
,MACHINEID
,SOURCEID
,PCPROCESSID
,IS_STATE
,AVERAGEVALUE
,SUMVALUE
,MINVALUE
,MAXVALUE
,SAMPLECOUNT
,PACKAGECOUNTER
)
SELECT
@INTERVALSTARTDATETIME
,P.PCTYPEID
,P.MACHINEID
,P.SOURCEID
,P.PCPROCESSID
,P.IS_STATE
,AVG(P.SUMVALUE)
,SUM(P.SUMVALUE)
,MIN(P.SUMVALUE)
,MAX(P.SUMVALUE)
,COUNT(*)
,MIN(PACK.PACKAGECOUNTER)
FROM
APM.PERFHOURLY P
JOIN #PCOUNTERAGGREGATE_TMP PACK ON PACK.MACHINEID = P.MACHINEID AND PACK.PCTYPEID = P.PCTYPEID
WHERE
(COALESCE(P.SUMVALUE, 0) &lt;&gt; 0)
AND (P.UTCDATE &gt;= @INTERVALSTARTDATETIME)
AND (P.UTCDATE &lt; @INTERVALENDDATETIME)
GROUP BY
P.PCTYPEID
,P.MACHINEID
,P.SOURCEID
,P.PCPROCESSID
,P.IS_STATE

QUIT:
QUITERROR:
RETURN @ERROR
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.RUNDAILYAGGREGATEOPERATION'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.RUNDAILYAGGREGATEOPERATION AS RETURN 1')
END
GO

ALTER PROCEDURE APM.RUNDAILYAGGREGATEOPERATION
@DATASETNAME NVARCHAR(50)
,@DESCRIPTORS NTEXT
,@AGGREGATIONTARGETSTOPDATETIME DATETIME
,@TRACELEVEL INT
AS
BEGIN
SET NOCOUNT ON

DECLARE
@ERROR INT
,@STARTDATE DATETIME
,@ENDDATE DATETIME
,@STEPCOUNT INT
,@MAXDAILYDATAAGEDAYS INT
,@MAXHOURLYDATAAGEDAYS INT
,@MAXDAILYHISTORYDATE DATETIME
,@MAXHOURLYHISTORYDATE DATETIME
,@UTCOFFSETMINUTES INT
,@UTCDATETIME DATETIME
,@CHECKDATE DATETIME
,@HANDLER INT
,@ROWCOUNT INT
,@RESLOCK BIT

SET @RESLOCK = 0
EXECUTE @ERROR = SP_GETAPPLOCK
@RESOURCE = N'RUNDAILYAGGREGATEOPERATION'
,@LOCKMODE = N'Exclusive'
,@LOCKOWNER = N'Session'
,@LOCKTIMEOUT = '0'

IF @ERROR = 0
SET @RESLOCK = 1
IF @ERROR &lt;&gt; 0
BEGIN
IF @ERROR = -1 SET @ERROR = 0
GOTO QUIT
END

SET @ERROR = 0

SET @UTCOFFSETMINUTES = DATEDIFF(MINUTE, GETDATE(), GETUTCDATE())

SELECT
@ENDDATE = MAX(UTCDATE)
FROM
PERFHOURLY WITH (NOLOCK)
WHERE
UTCDATE &lt; @AGGREGATIONTARGETSTOPDATETIME
SET @ENDDATE = ISNULL(@ENDDATE, '19010101')

SET @UTCDATETIME = DATEADD(MINUTE, @UTCOFFSETMINUTES, CAST(CONVERT(CHAR(8), @ENDDATE, 112) AS DATETIME))
SET @ENDDATE = DATEADD(HH,DATEPART(HH, @UTCDATETIME), CAST(CONVERT(CHAR(8), @ENDDATE, 112) AS DATETIME))

SELECT @STARTDATE = MAX(H.AGGREGATIONDATETIME)
FROM APM.DATASETAGGREGATIONHISTORY H
JOIN DATASET D ON D.DATASETID = H.DATASETID AND D.DATASETNAME = @DATASETNAME
WHERE H.DIRTYIND = 0

IF @STARTDATE IS NULL
BEGIN
SELECT @STARTDATE = MIN(UTCDATE)
FROM PERFHOURLY WITH (NOLOCK)
WHERE UTCDATE &lt; @AGGREGATIONTARGETSTOPDATETIME
END
SET @STARTDATE = ISNULL(@STARTDATE, '19010101')

SET @STARTDATE = DATEADD(DD, -1, @STARTDATE)
SET @STEPCOUNT = ISNULL(DATEDIFF(DD, @STARTDATE, @ENDDATE), 0)

SET @CHECKDATE = DATEADD(HH,DATEPART(HH, @UTCDATETIME), CAST(CONVERT(CHAR(8), @STARTDATE, 112) AS DATETIME))

WHILE (DATEADD(DD, @STEPCOUNT + 1, @CHECKDATE) &gt; @ENDDATE)
BEGIN
SET @STEPCOUNT = @STEPCOUNT - 1
END
SET @ENDDATE = DATEADD(DD, -1, @ENDDATE)

IF (@STEPCOUNT &gt; 0)
BEGIN
EXEC APM.DATASETAGGREGATE
@DATASETNAME
,@DESCRIPTORS
,@AGGREGATIONTARGETSTARTDATETIME = @ENDDATE
,@INTERVALSTOAGGREGATE = @STEPCOUNT
,@RETURN = 0

SET @ERROR = @@ERROR

IF (@ERROR &lt;&gt; 0)
GOTO QUIT

SET @STEPCOUNT = @STEPCOUNT - 1
END

WHILE (@STEPCOUNT &gt; 0)
BEGIN
EXEC APM.DATASETAGGREGATE
@DATASETNAME
,@DESCRIPTORS
,@AGGREGATIONTARGETSTARTDATETIME = @ENDDATE
,@INTERVALSTOAGGREGATE = 1
,@RETURN = 0

IF (@ERROR &lt;&gt; 0)
GOTO QUIT

SET @STEPCOUNT = @STEPCOUNT - 1
END

SET @ERROR = @@ERROR

QUIT:
IF @RESLOCK = 1
BEGIN
EXECUTE SP_RELEASEAPPLOCK
@RESOURCE = N'RUNDAILYAGGREGATEOPERATION'
,@LOCKOWNER = N'Session'
END
RETURN @ERROR
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.HourlyTableInit'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.HourlyTableInit AS RETURN 1')
END
GO

alter procedure APM.HourlyTableInit
as
begin
declare
@DATE as datetime
,@ITERATOR as int

set @ITERATOR = 1
set @DATE = '19000101'
while @ITERATOR &lt;= 24
begin
insert into APM.HourlyTable Values(@DATE)
set @DATE = dateadd(hh, 1, @DATE)
set @ITERATOR = @ITERATOR + 1
end
end
GO

exec APM.HourlyTableInit
GO

drop procedure APM.HourlyTableInit
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.DISABLE_FOREIGN_KEYS'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.DISABLE_FOREIGN_KEYS AS RETURN 1')
END
GO
ALTER PROCEDURE APM.DISABLE_FOREIGN_KEYS
@DISABLE BIT = 1
AS
BEGIN

DECLARE
@SQL NVARCHAR(500),
@TABLENAME NVARCHAR(128),
@FOREIGNKEYNAME NVARCHAR(128)

-- A LIST OF ALL OF THE FOREIGN KEYS AND THE TABLE NAMES
DECLARE FOREIGNKEYCURSOR CURSOR
FOR
SELECT
REF.CONSTRAINT_NAME AS FK_NAME,
FK.TABLE_NAME AS FK_TABLE
FROM
INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS REF
INNER JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS FK ON REF.CONSTRAINT_NAME = FK.CONSTRAINT_NAME
ORDER BY
FK.TABLE_NAME,
REF.CONSTRAINT_NAME

OPEN FOREIGNKEYCURSOR

FETCH NEXT FROM FOREIGNKEYCURSOR INTO @FOREIGNKEYNAME, @TABLENAME
WHILE ( @@FETCH_STATUS = 0 )
BEGIN
IF @DISABLE = 1
SET @SQL = N'ALTER TABLE [' + @TABLENAME + N'] NOCHECK CONSTRAINT [' + @FOREIGNKEYNAME + ']'
ELSE
SET @SQL = N'ALTER TABLE [' + @TABLENAME + N'] CHECK CONSTRAINT [' + @FOREIGNKEYNAME + ']'
PRINT 'EXECUTING STATEMENT - ' + @SQL
EXECUTE(@SQL)
FETCH NEXT FROM FOREIGNKEYCURSOR INTO @FOREIGNKEYNAME, @TABLENAME
END

CLOSE FOREIGNKEYCURSOR

DEALLOCATE FOREIGNKEYCURSOR

END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.SHOWMESSAGE'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.SHOWMESSAGE AS RETURN 1')
END
GO

ALTER PROCEDURE APM.SHOWMESSAGE @MESSAGE NVARCHAR(100) AS
BEGIN
RAISERROR (@MESSAGE, 0, 1) WITH NOWAIT
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.FILLGROUPS'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.FILLGROUPS AS RETURN 1')
END
GO
/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: FILLGROUPS */
/* DESCRIPTION: The procedure create resource group node only for the */
/* performance events. It will be called only if rowdata contains */
/* resource group section. */
/* INPUT PARAMETERS: */
/* @ROWGUID - unique identifier of the event record */
/* @GROUPSDOC - xml resource group package for processing */
/* &lt;callGroups&gt; */
/* &lt;callGroup name="{resource group}" */
/* duration="{duration,ms}" */
/* count="{call count}" /&gt; */
/* ... */
/* &lt;callGroup/&gt; */
/* &lt;/callGroups&gt; */
/* @TRACELEVEL - trace level */
/************************************************************************************/
ALTER PROCEDURE APM.FILLGROUPS
@ROWGUID NVARCHAR(15)
,@GROUPSDOC NTEXT
,@TRACELEVEL INT
AS
BEGIN
SET NOCOUNT ON

-- temporary table. Possible it is need to reseach using temporary variable ---
CREATE TABLE #GROUPS (NAME NVARCHAR(255) collate database_default, CALLCOUNT INT, DURATION BIGINT)

-- memory identifier
DECLARE @IDOC INT

-- error code
DECLARE @ERR INT

-- primary key for the @ROWGUID parameter
DECLARE @EVENTID BIGINT

-- row affected records
DECLARE @ROWAFFECTED AS INT

-- temporary variable for row affected records
DECLARE @RECORDCOUNT INT

-- error proccesing
DECLARE
@ERRORIND bit
,@ERRORNUMBER int
,@ERRORSEVERITY int
,@ERRORSTATE int
,@ERRORLINE int
,@ERRORPROCEDURE nvarchar(256)
,@ERRORMESSAGETEXT nvarchar(max)
,@ERROR_MESSAGE nvarchar(max)
,@MESSAGE nvarchar(max)

-- reset error flag
SET @ERRORIND = 0

BEGIN TRY

-- get event primary key using idx_T_RowGuid
SELECT @EVENTID = EventId FROM Event e(NOLOCK) WHERE e.rowGuid = @ROWGUID

IF (@@ROWCOUNT = 0)
BEGIN
-- raise exception "{rowguid} not found"
SELECT @ERROR_MESSAGE = message FROM APM.messages WHERE id = 50006
RAISERROR(@ERROR_MESSAGE, 16, 1, 'FILLGROUPS', @ROWGUID)
END

-- allocate memory for xml processing
EXEC @ERR = SP_XML_PREPAREDOCUMENT @IDOC OUTPUT, @GROUPSDOC
IF @ERR &lt;&gt; 0
BEGIN
-- raise exception
SELECT @ERROR_MESSAGE = message FROM APM.messages WHERE id = 50002
RAISERROR(@ERROR_MESSAGE, 16, 1, 'FILLGROUPS', @ERR)
END

-- Parse xml package
INSERT INTO #GROUPS
SELECT NAME, CALLCOUNT, DURATION
FROM OPENXML(@IDOC, N'/callGroups/callGroup', 2)
WITH (NAME NVARCHAR(255) N'@name', CALLCOUNT INT N'@count', DURATION BIGINT N'@duration')

SELECT @ROWAFFECTED = @@ROWCOUNT

-- free memory
EXEC SP_XML_REMOVEDOCUMENT @IDOC

SET @IDOC = NULL

IF (@TRACELEVEL = 4 AND @ROWAFFECTED = 0)
BEGIN
-- trace message
SELECT @MESSAGE = message FROM APM.Messages WHERE ID = 50007
RAISERROR (@MESSAGE, 0, 1) WITH NOWAIT;
END

-- if resource group exists
IF @ROWAFFECTED &gt; 0
BEGIN
-- create resource group
INSERT INTO APM.RESOURCEGROUP (NAME)
SELECT DISTINCT APM.GETRESOURCETYPE(G.NAME) FROM #GROUPS G
WHERE NOT EXISTS
(
SELECT * FROM RESOURCEGROUP RG (NOLOCK) WHERE RG.NAME = APM.GETRESOURCETYPE(G.NAME)
)

SELECT @RECORDCOUNT = @@ROWCOUNT
IF (@TRACELEVEL = 4)
BEGIN
-- trace message
SELECT @MESSAGE = message FROM APM.Messages WHERE ID = 50008
RAISERROR (@MESSAGE, 0, 1, @RECORDCOUNT) WITH NOWAIT;
END

-- Check exitsing internal resource group. It is need to create.
IF NOT EXISTS(SELECT * FROM RESOURCEGROUP RG (NOLOCK) WHERE RG.NAME = N'Internal')
INSERT INTO RESOURCEGROUP(NAME) VALUES (N'Internal')

-- create resource group node for all resourtce calls
;WITH RESOURCEGROUPNODESET(EVENTID, DURATION, CALLCOUNT, RESOURCEGROUPID) AS
(
-- by resource group calls from package
SELECT
@EVENTID EVENTID,
SUM(G.DURATION) DURATION,
SUM(G.CALLCOUNT) CALLCOUNT,
RG.RESOURCEGROUPID
FROM
#GROUPS G
JOIN
RESOURCEGROUP RG (NOLOCK) ON RG.NAME = APM.GETRESOURCETYPE(G.NAME)
GROUP BY
RG.RESOURCEGROUPID

UNION ALL

-- calculate internal call group as
SELECT
EVENTID, DURATION, CALLCOUNT, RESOURCEGROUPID
FROM
(
SELECT
@EVENTID EVENTID,
-- Rule: event duration - all resource group call
COALESCE(E.EVENTDURATION, 0) / 1000 - COALESCE(A.DURATION, 0) DURATION,
NULL CALLCOUNT,
(SELECT RESOURCEGROUPID FROM RESOURCEGROUP RG WHERE RG.NAME = N'Internal') RESOURCEGROUPID
FROM
EVENT E (NOLOCK)
CROSS JOIN
(
SELECT
SUM(G.DURATION) DURATION
FROM
#GROUPS G
) A
WHERE
E.EVENTID = @EVENTID
) B
WHERE B.DURATION &gt; 0
),
-- grouping result by resource group
RESOURCEGROUPNODESETUNIQ(EVENTID, DURATION, CALLCOUNT, RESOURCEGROUPID) AS
(
SELECT
@EVENTID, SUM(DURATION), SUM(CALLCOUNT), RESOURCEGROUPID
FROM
RESOURCEGROUPNODESET
GROUP BY
RESOURCEGROUPID
)
-- create resource group node
INSERT INTO RESOURCEGROUPNODE(EVENTID, DURATION, CALLCOUNT, RESOURCEGROUPID)
SELECT
EVENTID, DURATION, CALLCOUNT, RESOURCEGROUPID
FROM
RESOURCEGROUPNODESETUNIQ

SELECT @RECORDCOUNT = @@ROWCOUNT
IF (@TRACELEVEL = 4)
BEGIN
-- trace level
SELECT @MESSAGE = message FROM APM.Messages WHERE ID = 50010
RAISERROR (@MESSAGE, 0, 1, @RECORDCOUNT) WITH NOWAIT;
END
END
END TRY
BEGIN CATCH
-- exception processing

-- check active transactions
IF (@@TRANCOUNT &gt; 0)
ROLLBACK TRAN

-- get context variables
SELECT
@ERRORNUMBER = ERROR_NUMBER()
,@ERRORSEVERITY = ERROR_SEVERITY()
,@ERRORSTATE = ERROR_STATE()
,@ERRORLINE = ERROR_LINE()
,@ERRORPROCEDURE = ISNULL(ERROR_PROCEDURE(), '-')
,@ERRORMESSAGETEXT = ERROR_MESSAGE()

-- switch error flag
SET @ERRORIND = 1
END CATCH
-- check memory handle
IF @IDOC IS NOT NULL
EXEC sp_xml_removedocument @IDOC

-- report error if any
IF (@ERRORIND = 1)
BEGIN
DECLARE @ADJUSTEDERRORSEVERITY int

SET @ADJUSTEDERRORSEVERITY = CASE
WHEN @ERRORSEVERITY &gt; 18 THEN 18
ELSE @ERRORSEVERITY
END

SELECT @ERROR_MESSAGE = message FROM APM.Messages WHERE id = 50004
RAISERROR (@ERROR_MESSAGE, @ADJUSTEDERRORSEVERITY, 1
,@ERRORNUMBER
,@ERRORSEVERITY
,@ERRORSTATE
,@ERRORPROCEDURE
,@ERRORLINE
,@ERRORMESSAGETEXT
)
END
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.FillResourceGroupNodes'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.FillResourceGroupNodes AS RETURN 1')
END
GO
/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: FillResourceGroupNodes */
/* DESCRIPTION: The procedure create resource group node for the performance nodes */
/* This is internal stored procedure. It is used by FillResource */
/* stored procedure. The FillResourceGroupNodes use external */
/* temporary table. Existing resource group node is not check. */
/* INPUT PARAMETERS: */
/* @EVENTID - primary key of the event record */
/* @TRACELEVEL - trace level */
/************************************************************************************/
ALTER PROCEDURE APM.FillResourceGroupNodes
@EVENTID bigint
,@TRACELEVEL int
AS
BEGIN
SET NOCOUNT ON;

DECLARE
@MESSAGE nvarchar(max)
,@RECORDCOUNT int

IF @TRACELEVEL = 4
BEGIN
-- trace message
SELECT @MESSAGE = MESSAGE FROM APM.MESSAGES WHERE ID = 50031
RAISERROR (@MESSAGE, 0, 1) WITH NOWAIT;
END

;WITH ResourceGroupNodeSet(DURATION, RESOURCEGROUPID) AS
(
-- grouping resources from xml resource package
SELECT
SUM(D.DUR) DURATION,
D.RESOURCEGROUPID
FROM
#DETAILS D
GROUP BY
D.RESOURCEGROUPID

UNION ALL

-- calculate one internal execution. Internal resource group should be create before.
SELECT
DURATION, RESOURCEGROUPID
FROM
(
SELECT
-- calculation rule: event duration - all resource call group duration
COALESCE(A.EVENTDURATION, 0) / 1000 - COALESCE(A.DURATION, 0) DURATION,
RG.RESOURCEGROUPID
FROM
RESOURCEGROUP RG (NOLOCK)
CROSS JOIN
(
-- all resource call group duration
SELECT
SUM(D.DUR) DURATION
,MIN(D.EVENTDURATION) EVENTDURATION
FROM
#DETAILS D
) A
WHERE
RG.NAME = N'Internal'
) B
WHERE B.DURATION &gt; 0
),
-- grouping by resource group
ResourceGroupNodeSetUniq(EVENTID, DURATION, CALLCOUNT, RESOURCEGROUPID) AS
(
SELECT
@EVENTID, SUM(DURATION), NULL, RESOURCEGROUPID
FROM
ResourceGroupNodeSet
GROUP BY
RESOURCEGROUPID
)
INSERT INTO RESOURCEGROUPNODE(EVENTID, DURATION, CALLCOUNT, RESOURCEGROUPID)
SELECT
EVENTID, DURATION, CALLCOUNT, RESOURCEGROUPID
FROM
ResourceGroupNodeSetUniq

SELECT @RECORDCOUNT = @@ROWCOUNT

IF @TRACELEVEL = 4
BEGIN
-- trace level
SELECT @MESSAGE = MESSAGE FROM APM.MESSAGES WHERE ID = 50032
RAISERROR (@MESSAGE, 0, 1, N'FILLRESOURCEGROUPNODES', @RECORDCOUNT, N'RESOURCEGROUPNODE') WITH NOWAIT;
END
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.FILLRESOURCES'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.FILLRESOURCES AS RETURN 1')
END
GO
/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: FILLRESOURCES */
/* DESCRIPTION: The procedure update resource references on the performancenode, */
/* exceptionnode, event tables. If resource doesn't exist it */
/* will be create. If rowdata doesn't contain resource group call */
/* section resource group node will be create on the */
/* resourcegroupnode table for the performance events. */
/* INPUT PARAMETERS: */
/* @ROWGUID - unique identifier of the event record */
/* @DETAILSDOC - xml resource package for processing */
/* &lt;resources&gt; */
/* &lt;resource entryId="{entry id}" quick="{0(1)}"&gt; */
/* &lt;method dur="{duration, ms}"&gt;{method name}&lt;/method&gt; */
/* &lt;uriFormat&gt;{uri format}&lt;/uriFormat&gt; */
/* &lt;type&gt;{resource type}&lt;/type&gt; */
/* &lt;/resource&gt; */
/* ... */
/* &lt;resource/&gt; */
/* &lt;/resources&gt; */
/* quick attribute values: */
/* 1 quick resource call */
/* 0 not quick resource call */
/* resource method format: */
/* {namespace}${resource call} */
/* {uri format} reserved */
/* @TRACELEVEL - trace level */
/************************************************************************************/
ALTER PROCEDURE [APM].[FILLRESOURCES]
@ROWGUID NVARCHAR(15)
,@DETAILSDOC NTEXT
,@TRACELEVEL INT
AS
BEGIN
SET NOCOUNT ON

-- memory identifier
DECLARE @IDOC INT

-- error code
DECLARE @ERR INT
-- event class type
DECLARE @EVENTCLASSTYPE NVARCHAR(255)

-- primary key for the @ROWGUID parameter
DECLARE @EVENTID BIGINT

-- row affected records
DECLARE @ROWAFFECTED AS INT

-- trace message
DECLARE @MESSAGE NVARCHAR(MAX)

-- temporary variable for row affected records
DECLARE @RECORDCOUNT INT

-- error proccesing
DECLARE
@ERRORIND bit
,@ERRORNUMBER int
,@ERRORSEVERITY int
,@ERRORSTATE int
,@ERRORLINE int
,@ERRORPROCEDURE nvarchar(256)
,@ERRORMESSAGETEXT nvarchar(max)
,@ERROR_MESSAGE nvarchar(max)

-- reset error flag
SET @ERRORIND = 0

BEGIN TRY

-- temporary table. Possible it is need to reseach using temporary variable ---
CREATE TABLE #DETAILS (
ENTRYID INT
,METHOD nvarchar(255) collate database_default
,RESOURCEURI nvarchar(255) collate database_default
,URIFORMAT NVARCHAR(255) collate database_default
,TYPE NVARCHAR(255) collate database_default
,QUICK INT
,DUR decimal(35,0)
,RESOURCEGROUPID int
,SOURCEID int
,EVENTID bigint
,EVENTDURATION decimal(35,0)
)

-- get event primary key using idx_T_RowGuid
SELECT @EVENTID = EventId FROM APM.Event e(NOLOCK) WHERE e.rowGuid = @ROWGUID
IF (@@ROWCOUNT = 0)
BEGIN
-- raise exception "{rowguid} not found"
SELECT @ERROR_MESSAGE = message FROM APM.messages WHERE id = 50006
RAISERROR(@ERROR_MESSAGE, 16, 1, 'FILLRESOURCES', @ROWGUID)
END

-- allocate memory for xml processing
EXEC @ERR = SP_XML_PREPAREDOCUMENT @IDOC OUTPUT, @DETAILSDOC
IF @ERR &lt;&gt; 0
BEGIN
-- raise exception
SELECT @ERROR_MESSAGE = message FROM APM.messages WHERE id = 50002
RAISERROR(@ERROR_MESSAGE, 16, 1, 'FILLRESOURCES', @ERR)
END

-- Parse xml package
INSERT INTO #DETAILS
SELECT ENTRYID, METHOD, APM.GETRESOURCE(METHOD), URIFORMAT, TYPE, QUICK, DUR, 0, 0, 0, 0
FROM OPENXML(@IDOC, N'/resources/resource', 2)
WITH (
ENTRYID INT N'@entryId',
METHOD NVARCHAR(255) N'method',
URIFORMAT NVARCHAR(255) N'uriFormat',
TYPE NVARCHAR(255) N'type',
QUICK INT N'@quick',
DUR decimal(35,0) N'method/@dur'
)
SELECT @ROWAFFECTED = @@ROWCOUNT

-- free memory
EXEC SP_XML_REMOVEDOCUMENT @IDOC

SET @IDOC = NULL

IF @TRACELEVEL = 4 AND @ROWAFFECTED = 0
BEGIN
-- resources is empty
SELECT @MESSAGE = MESSAGE FROM APM.MESSAGES WHERE ID = 50013
RAISERROR (@MESSAGE, 0, 1) WITH NOWAIT;
END

-- if resources exists
IF @ROWAFFECTED &gt; 0
BEGIN

-- get event class type using index idx_T_EventId
SELECT
@EVENTCLASSTYPE = EVENTCLASSTYPE
FROM
APM.EVENT E (NOLOCK)
WHERE
E.EVENTID = @EVENTID

-- create resource group
INSERT INTO APM.RESOURCEGROUP (NAME)
SELECT DISTINCT APM.GETRESOURCETYPE(D.TYPE) FROM #DETAILS D
WHERE NOT EXISTS
(
SELECT * FROM APM.RESOURCEGROUP RG (NOLOCK) WHERE RG.NAME = APM.GETRESOURCETYPE(D.TYPE)
)

-- updating additional fields. It is need for decrease number of join operations.
UPDATE D
SET
D.RESOURCEGROUPID = RG.RESOURCEGROUPID
,D.SOURCEID = E.SOURCEID
,D.EVENTID = E.EVENTID
,D.EVENTDURATION = E.EVENTDURATION
FROM #DETAILS D
JOIN RESOURCEGROUP RG (NOLOCK) ON RG.NAME = APM.GETRESOURCETYPE(D.TYPE)
CROSS JOIN (SELECT EVENTID, SOURCEID, EVENTDURATION FROM APM.EVENT E (NOLOCK) WHERE E.EVENTID = @EVENTID) E

-- Check exitsing internal resource group. It is need to create.
IF NOT EXISTS(SELECT * FROM APM.RESOURCEGROUP RG (NOLOCK) WHERE RG.NAME = N'Internal')
INSERT INTO RESOURCEGROUP(NAME) VALUES (N'Internal')

-- create resource for all methods
INSERT INTO RESOURCE(
SOURCEID,
RESOURCEGROUPID,
RESOURCEURIFORMAT,
RESOURCEURI
)
SELECT
DISTINCT D.SOURCEID, D.RESOURCEGROUPID, D.URIFORMAT, D.RESOURCEURI
FROM
#DETAILS D
WHERE
NOT EXISTS(
SELECT *
FROM
APM.RESOURCE R (NOLOCK)
WHERE
R.SOURCEID = D.SOURCEID
AND R.RESOURCEGROUPID = D.RESOURCEGROUPID
AND R.RESOURCEURI = D.RESOURCEURI
)

SELECT @RECORDCOUNT = @@ROWCOUNT

IF @TRACELEVEL = 4
BEGIN
-- send info message about resource row affected
SELECT @MESSAGE = MESSAGE FROM APM.MESSAGES WHERE ID = 50014
RAISERROR (@MESSAGE, 0, 1, @RECORDCOUNT) WITH NOWAIT;
END

IF @EVENTCLASSTYPE = N'performance' AND EXISTS (SELECT * FROM #DETAILS WHERE QUICK = 0)
BEGIN
-- processing performance events for not quick resource calls
IF @TRACELEVEL = 4
BEGIN
-- trace info message
SELECT @MESSAGE = MESSAGE FROM APM.MESSAGES WHERE ID = 50015
RAISERROR (@MESSAGE, 0, 1) WITH NOWAIT;
END

-- Create resource group node if rowdata doesn't containt resource call group section or it is empty
IF NOT EXISTS(SELECT * FROM RESOURCEGROUPNODE RN WHERE RN.EventId = @EVENTID)
EXEC APM.FillResourceGroupNodes @EVENTID, @TRACELEVEL

--Check existing performance node
IF NOT EXISTS(SELECT * FROM APM.PERFORMANCENODE P (NOLOCK) WHERE P.EVENTID = @EVENTID)
BEGIN
-- It is need create performance node(s) for not quick resource call
IF @TRACELEVEL = 4
BEGIN
-- trace message
SELECT @MESSAGE = MESSAGE FROM APM.MESSAGES WHERE ID = 50016
RAISERROR (@MESSAGE, 0, 1) WITH NOWAIT;
END

INSERT INTO APM.PERFORMANCENODE
(
EVENTID,
DESCRIPTION,
FUNCTIONNAME,
ENTRYID,
DURATION,
SELFDURATION,
ISHEAVIESTNODE
)
SELECT
@EVENTID,
REPLACE(D.METHOD,'$',''),
REPLACE(D.METHOD,'$',''),
D.ENTRYID,
D.DUR,
D.DUR,
1
FROM
#DETAILS D
WHERE
D.QUICK = 0

SELECT @RECORDCOUNT = @@ROWCOUNT

IF @TRACELEVEL = 4
BEGIN
-- trace info message
SELECT @MESSAGE = MESSAGE FROM APM.MESSAGES WHERE ID = 50017
RAISERROR (@MESSAGE, 0, 1, @RECORDCOUNT) WITH NOWAIT;
END
END
-- update resource, resource group node references and resource method for not quick resource calls
UPDATE P SET
P.RESOURCEID = R.RESOURCEID,
P.RESOURCEGROUPNODEID = RGN.RESOURCEGROUPNODEID,
P.RESOURCEMETHOD = REPLACE(D.METHOD, N'$', N''), -- full method name (namespace + resource function call)
P.SELFDURATION = D.DUR
FROM
PERFORMANCENODE P
JOIN #DETAILS D ON D.ENTRYID = P.ENTRYID AND D.QUICK = 0
JOIN RESOURCEGROUPNODE RGN (NOLOCK) ON RGN.RESOURCEGROUPID = D.RESOURCEGROUPID AND RGN.EVENTID = D.EVENTID
JOIN RESOURCE R (NOLOCK) ON R.RESOURCEURI = D.RESOURCEURI AND R.SOURCEID = D.SOURCEID AND R.RESOURCEGROUPID = D.RESOURCEGROUPID
WHERE
P.EVENTID = @EVENTID

SELECT @RECORDCOUNT = @@ROWCOUNT
IF @TRACELEVEL = 4
BEGIN
-- trace message
SELECT @MESSAGE = MESSAGE FROM APM.MESSAGES WHERE ID = 50018
RAISERROR (@MESSAGE, 0, 1, @RECORDCOUNT) WITH NOWAIT;
END
-- update event resource reference. It will be reference to the most heavy resources
UPDATE E SET
E.RESOURCEID = (
SELECT TOP 1
P.RESOURCEID
FROM
PERFORMANCENODE P (NOLOCK)
WHERE
P.EVENTID = @EVENTID
ORDER BY
P.SELFDURATION DESC, P.PERFORMANCENODEID DESC
)
FROM
APM.EVENT E
WHERE
E.EVENTID = @EVENTID

SELECT @RECORDCOUNT = @@ROWCOUNT
IF @TRACELEVEL = 4
BEGIN
-- trace message
SELECT @MESSAGE = MESSAGE FROM APM.MESSAGES WHERE ID = 50020
RAISERROR (@MESSAGE, 0, 1, @RECORDCOUNT) WITH NOWAIT;
END
END

IF @EVENTCLASSTYPE = N'exception' AND EXISTS(SELECT * FROM APM.EXCEPTIONNODE EX (NOLOCK) WHERE EX.EVENTID = @EVENTID)
BEGIN
-- processing exception event

-- update resource reference and resource method
UPDATE EX SET
EX.RESOURCEID = R.RESOURCEID,
EX.RESOURCEMETHOD = REPLACE(D.METHOD, N'$', N'') -- full method name (namespace + resource function call)
FROM APM.EXCEPTIONNODE EX
CROSS JOIN (SELECT METHOD, SOURCEID, RESOURCEURI,RESOURCEGROUPID FROM #DETAILS D WHERE QUICK = 0) D
JOIN APM.RESOURCE R (NOLOCK) ON R.RESOURCEURI = D.RESOURCEURI AND R.SOURCEID = D.SOURCEID AND R.RESOURCEGROUPID = D.RESOURCEGROUPID
WHERE
EX.EVENTID = @EVENTID

SELECT @RECORDCOUNT = @@ROWCOUNT
IF @TRACELEVEL = 4
BEGIN
-- trace info message
SELECT @MESSAGE = MESSAGE FROM APM.MESSAGES WHERE ID = 50021
RAISERROR (@MESSAGE, 0, 1, @RECORDCOUNT) WITH NOWAIT;
END

-- update event resource reference.
UPDATE E SET
E.RESOURCEID = (
SELECT TOP 1
EX.RESOURCEID
FROM
APM.EXCEPTIONNODE EX (NOLOCK)
WHERE
EX.EVENTID = @EVENTID
ORDER BY
EX.RESOURCEID
)
FROM
APM.EVENT E
WHERE
E.EVENTID = @EVENTID

SELECT @RECORDCOUNT = @@ROWCOUNT
IF @TRACELEVEL = 4
BEGIN
-- trace info message
SELECT @MESSAGE = MESSAGE FROM APM.MESSAGES WHERE ID = 50022
RAISERROR (@MESSAGE, 0, 1, @RECORDCOUNT) WITH NOWAIT;
END

END
END
END TRY
BEGIN CATCH
-- exception processing

-- check active transactions
IF (@@TRANCOUNT &gt; 0)
ROLLBACK TRAN

-- get context variables
SELECT
@ERRORNUMBER = ERROR_NUMBER()
,@ERRORSEVERITY = ERROR_SEVERITY()
,@ERRORSTATE = ERROR_STATE()
,@ERRORLINE = ERROR_LINE()
,@ERRORPROCEDURE = ISNULL(ERROR_PROCEDURE(), '-')
,@ERRORMESSAGETEXT = ERROR_MESSAGE()

-- switch error flag
SET @ERRORIND = 1
END CATCH

-- check memory handle
IF @IDOC IS NOT NULL
EXEC sp_xml_removedocument @IDOC

--report error if any
IF (@ERRORIND = 1)
BEGIN
DECLARE @ADJUSTEDERRORSEVERITY int

SET @ADJUSTEDERRORSEVERITY = CASE
WHEN @ERRORSEVERITY &gt; 18 THEN 18
ELSE @ERRORSEVERITY
END

SELECT @ERROR_MESSAGE = message FROM APM.Messages WHERE id = 50004
RAISERROR (@ERROR_MESSAGE, @ADJUSTEDERRORSEVERITY, 1
,@ERRORNUMBER
,@ERRORSEVERITY
,@ERRORSTATE
,@ERRORPROCEDURE
,@ERRORLINE
,@ERRORMESSAGETEXT
)
END
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.UpdateEventsByInternalResource'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.UpdateEventsByInternalResource AS RETURN 1')
END
GO
/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: UpdateEventsByInternalResource */
/* DESCRIPTION: The procedure update resource reference for events */
/* This is internal stored procedure. It is used by FillResource */
/* stored procedure. The UpdateEventsByInternalResource use external */
/* temporary table. */
/* INPUT PARAMETERS: */
/* @EVENTCLASSTYPE - event class type */
/* @TRACELEVEL - trace level */
/************************************************************************************/
ALTER PROCEDURE APM.UpdateEventsByInternalResource @EVENTCLASSTYPE nvarchar(255)
AS
BEGIN
if (@EVENTCLASSTYPE = N'performance')
begin
-- processing performance events
UPDATE E
SET E.RESOURCEID = A.RESOURCEID
FROM
APM.EVENT E
JOIN #FILLINTERNALRESOURCESTABLE F ON F.EVENTID = E.EVENTID
CROSS APPLY (
-- using haviest resource
SELECT TOP 1
P.RESOURCEID
FROM
APM.PERFORMANCENODE P (NOLOCK)
WHERE
P.EVENTID = E.EVENTID
ORDER BY
P.SELFDURATION DESC,
P.PERFORMANCENODEID
) A
end
if @EVENTCLASSTYPE = N'exception'
begin
-- processing exception events
UPDATE E
SET E.RESOURCEID = A.RESOURCEID
FROM
APM.EVENT E
JOIN #FILLINTERNALRESOURCESTABLE F ON F.EVENTID = E.EVENTID
CROSS APPLY (
SELECT TOP 1
EX.RESOURCEID
FROM
APM.EXCEPTIONNODE EX (NOLOCK)
WHERE
EX.EVENTID = E.EVENTID
ORDER BY
EX.EXCEPTIONNODEID
) A
end
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.INSERTINTERNALRESOURCE'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.INSERTINTERNALRESOURCE AS RETURN 1')
END
GO
/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: INSERTINTERNALRESOURCE */
/* DESCRIPTION: The procedure create internal execution resource. */
/* This is internal stored procedure. It is used by */
/* FillInternalResource stored procedure and use external temporary */
/* table. */
/************************************************************************************/
ALTER PROCEDURE APM.INSERTINTERNALRESOURCE
AS
BEGIN
DECLARE @INTERNALRESOURCEGROUPID int

SELECT
-- get primary key for internal resource group
@INTERNALRESOURCEGROUPID = RESOURCEGROUPID FROM APM.RESOURCEGROUP RG WHERE RG.NAME = N'Internal'

-- create internal execution resource for temporary sources
INSERT INTO RESOURCE (RESOURCEGROUPID, SOURCEID, RESOURCEURI, RESOURCEURIFORMAT)
SELECT DISTINCT
@INTERNALRESOURCEGROUPID
,F.SOURCEID
,N'Internal Execution'
,N''
FROM
#FILLINTERNALRESOURCESTABLE F
WHERE
NOT EXISTS(
SELECT *
FROM APM.RESOURCE R (NOLOCK)
WHERE
R.SOURCEID = F.SOURCEID
AND R.RESOURCEURI = N'Internal Execution'
)
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.FILLINTERNALRESOURCES'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.FILLINTERNALRESOURCES AS RETURN 1')
END
GO
/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: FILLINTERNALRESOURCES */
/* DESCRIPTION: The procedure update resource references on the performancenode, */
/* exceptionnode, event tables which is empty. The new resource */
/* will be internal execution. After execution this procedure "heavy */
/* light" events should be performance or exception nodes. Events will*/
/* process by block starting @STARTROWGUID and ending @ENDROWGUID */
/* */
/* INPUT PARAMETERS: */
/* @STARTROWGUID - start block unique identifier */
/* @ENDBLOCK - end block unique identifier */
/* @DATABASEID - database identifier */
/* @RECORDCOUNT - reserved */
/* @TRACELEVEL - trace level */
/************************************************************************************/
ALTER PROCEDURE APM.FILLINTERNALRESOURCES
@STARTROWGUID NVARCHAR(15)
,@ENDROWGUID NVARCHAR(15)
,@DATABASEID INT
,@RECORDCOUNT INT
,@TRACELEVEL INT
AS
BEGIN
SET NOCOUNT ON

DECLARE @RECORDS INT
DECLARE @MESSAGE NVARCHAR(MAX)

-- error proccesing
DECLARE
@ERRORIND bit
,@ERRORNUMBER int
,@ERRORSEVERITY int
,@ERRORSTATE int
,@ERRORLINE int
,@ERRORPROCEDURE nvarchar(256)
,@ERRORMESSAGETEXT nvarchar(max)
,@ERROR_MESSAGE nvarchar(max)

-- reset error flag
SET @ERRORIND = 0

BEGIN TRY

DECLARE
-- starting primary key
@STARTID bigint
-- ending primary key
,@ENDID bigint
-- internal resource group
,@INTERNALRESOURCEGROUPID int

IF NOT EXISTS(SELECT * FROM APM.RESOURCEGROUP WHERE NAME = N'Internal')
INSERT INTO APM.RESOURCEGROUP(NAME) VALUES (N'Internal')

-- Get primary key internal resource group
SELECT
@INTERNALRESOURCEGROUPID = RESOURCEGROUPID FROM APM.RESOURCEGROUP RG WHERE RG.NAME = N'Internal'

-- Get event primary keys
SELECT
@STARTID = CASE WHEN ROWGUID = @STARTROWGUID THEN eventId ELSE @STARTID END
,@ENDID = CASE WHEN ROWGUID = @ENDROWGUID THEN eventId ELSE @ENDID END
FROM
APM.EVENT (NOLOCK)
WHERE
ROWGUID IN (@STARTROWGUID, @ENDROWGUID)

IF @STARTID IS NULL OR @ENDID IS NULL
BEGIN
DECLARE
@MSG nvarchar(MAX)

SELECT @MSG = message FROM APM.MESSAGES(NOLOCK) WHERE id = 50035
RAISERROR(@MSG, 16, 1, @STARTROWGUID, @ENDROWGUID)
RETURN
END


-- temporary event table. Do not use temporary table variable because table is used by internal stored procedures
CREATE TABLE #FILLINTERNALRESOURCESTABLE
(
EVENTID INT
,SOURCEID INT
,EVENTDURATION DECIMAL(35,0)
,EXCEPTIONCLASS NVARCHAR(255) collate database_default
,DESCRIPTION NVARCHAR(255) collate database_default
)

/* Processing performance events which are not have performance nodes */
INSERT INTO #FILLINTERNALRESOURCESTABLE(EVENTID,EVENTDURATION,SOURCEID)
SELECT
E.EVENTID, E.EVENTDURATION,E.SOURCEID
FROM
APM.EVENT (NOLOCK) E
WHERE
E.SEVIEWERDBID = @DATABASEID
AND E.EVENTID &gt;= @STARTID AND E.EVENTID &lt;= @ENDID
AND (HEAVYLIGHT IS NULL OR HEAVYLIGHT &lt;&gt; 0)
AND NOT EXISTS(SELECT * FROM PERFORMANCENODE P (NOLOCK) WHERE P.EVENTID = E.EVENTID)
AND E.EVENTCLASSTYPE = N'performance' OPTION(RECOMPILE)

IF (@@ROWCOUNT &gt; 0)
BEGIN
-- Processing performance events

-- Delete old resource group nodes
DELETE R FROM
APM.RESOURCEGROUPNODE R
JOIN #FILLINTERNALRESOURCESTABLE F ON F.EVENTID = R.EVENTID

--Insert internal resource group node
INSERT RESOURCEGROUPNODE(EVENTID, DURATION, CALLCOUNT, RESOURCEGROUPID)
SELECT
F.EVENTID,
-- use event duration
COALESCE(F.EVENTDURATION, 0) / 1000 AS DURATION,
NULL AS CALLCOUNT,
@INTERNALRESOURCEGROUPID
FROM
#FILLINTERNALRESOURCESTABLE F

-- create internal execution resource for event sources
EXEC APM.InsertInternalResource

-- create performance node
INSERT INTO APM.PERFORMANCENODE
(
EVENTID,
RESOURCEID,
RESOURCEGROUPNODEID,
DESCRIPTION,
FUNCTIONNAME,
RESOURCEMETHOD,
DURATION,
ENTRYID,
SELFDURATION,
ISHEAVIESTNODE
)
SELECT
F.EVENTID,
R.RESOURCEID,
RGN.RESOURCEGROUPNODEID,
R.RESOURCEURI,
R.RESOURCEURI,
R.RESOURCEURI,
-- use event duration
F.EVENTDURATION / 1000,
0,
-- use event duration
F.EVENTDURATION / 1000,
--These events always have only one performance node which is most heavy
1
FROM
#FILLINTERNALRESOURCESTABLE F
JOIN APM.RESOURCEGROUPNODE RGN (NOLOCK) ON RGN.EVENTID = F.EVENTID
JOIN APM.RESOURCE R (NOLOCK) ON R.RESOURCEURI = N'Internal Execution' AND R.SOURCEID = F.SOURCEID

SET @RECORDS = @@ROWCOUNT

IF @TRACELEVEL = 4
BEGIN
-- trace message
DECLARE @PROCESSED INT
SELECT @PROCESSED = COUNT(*) FROM #FILLINTERNALRESOURCESTABLE
SELECT @MESSAGE = MESSAGE FROM APM.MESSAGES WHERE ID = 50028

RAISERROR (@MESSAGE, 0, 1, @PROCESSED, @RECORDS) WITH NOWAIT;
END

-- update event resource reference
EXEC APM.UpdateEventsByInternalResource N'performance'
END

/* Processing exception events which are not have exception nodes */
TRUNCATE TABLE #FILLINTERNALRESOURCESTABLE
INSERT INTO #FILLINTERNALRESOURCESTABLE(EVENTID,SOURCEID,EXCEPTIONCLASS,DESCRIPTION)
SELECT
E.EVENTID, E.SOURCEID, E.EXCEPTIONCLASS, E.DESCRIPTION
FROM
APM.EVENT (NOLOCK) E
WHERE
E.SEVIEWERDBID = @DATABASEID
AND E.EVENTID &gt;= @STARTID AND E.EVENTID &lt;= @ENDID
AND NOT EXISTS(SELECT * FROM EXCEPTIONNODE Ex (NOLOCK) WHERE Ex.EVENTID = E.EVENTID)
AND E.EVENTCLASSTYPE = N'exception' OPTION(RECOMPILE)
IF (@@ROWCOUNT &gt; 0)
BEGIN
-- create internal execution resource for event sources
EXEC APM.INSERTINTERNALRESOURCE

-- create exception node
INSERT INTO APM.EXCEPTIONNODE
(
EVENTID,
RESOURCEID,
EXCEPTIONCLASS,
FUNCTIONNAME,
RESOURCEMETHOD,
-- use event description
DESCRIPTION
)
SELECT
F.EVENTID,
R.RESOURCEID,
F.EXCEPTIONCLASS,
R.RESOURCEURI,
R.RESOURCEURI,
F.DESCRIPTION
FROM
#FILLINTERNALRESOURCESTABLE F
JOIN APM.RESOURCE R (NOLOCK) ON R.RESOURCEURI = N'Internal Execution' AND R.SOURCEID = F.SOURCEID

SELECT @RECORDS = @@ROWCOUNT

IF @TRACELEVEL = 4
BEGIN
-- trace message
SELECT @MESSAGE = MESSAGE FROM APM.MESSAGES WHERE ID = 50029
RAISERROR (@MESSAGE, 0, 1, @RECORDS) WITH NOWAIT;
END

-- update event resource reference
EXEC APM.UpdateEventsByInternalResource N'exception'
END


/* Processing performance nodes which are not have resources */
TRUNCATE TABLE #FILLINTERNALRESOURCESTABLE
INSERT INTO #FILLINTERNALRESOURCESTABLE(EVENTID,EVENTDURATION, SOURCEID)
SELECT
E.EVENTID, E.EVENTDURATION, E.SOURCEID
FROM
APM.EVENT (NOLOCK) E
WHERE
EXISTS(
SELECT * FROM APM.PERFORMANCENODE AS P(NOLOCK)
WHERE P.EVENTID = E.EVENTID AND P.RESOURCEID IS NULL
)
AND E.SEVIEWERDBID = @DATABASEID
AND E.EVENTID &gt;= @STARTID AND E.EVENTID &lt;= @ENDID
AND (E.HEAVYLIGHT IS NULL OR E.HEAVYLIGHT &lt;&gt; 0)
AND E.EVENTCLASSTYPE = N'performance' OPTION(RECOMPILE)

IF @@ROWCOUNT &gt; 0
BEGIN
--delete not linked resource nodes
DELETE RGN
FROM APM.RESOURCEGROUPNODE RGN
JOIN #FILLINTERNALRESOURCESTABLE F ON F.EVENTID = RGN.EVENTID
WHERE NOT EXISTS(SELECT * FROM APM.PERFORMANCENODE P (NOLOCK)
WHERE P.EVENTID = F.EVENTID AND P.RESOURCEGROUPNODEID = RGN.RESOURCEGROUPNODEID)
--Check existing internal group node
IF NOT EXISTS(
SELECT *
FROM APM.RESOURCEGROUPNODE AS RGN (NOLOCK)
JOIN #FILLINTERNALRESOURCESTABLE F ON F.EVENTID = RGN.EVENTID
WHERE
RGN.RESOURCEGROUPID = @INTERNALRESOURCEGROUPID
)
BEGIN
--Internal resource group is missing
--Create new
INSERT APM.RESOURCEGROUPNODE(EVENTID, DURATION, RESOURCEGROUPID)
SELECT
F.EVENTID,
-- use event duration
COALESCE(F.EVENTDURATION, 0) / 1000 - COALESCE(A.DURATION, 0) DURATION,
@INTERNALRESOURCEGROUPID
FROM
#FILLINTERNALRESOURCESTABLE F
CROSS APPLY
(
SELECT
SUM(DURATION) DURATION
FROM
APM.RESOURCEGROUPNODE AS RGN (NOLOCK) WHERE RGN.EVENTID = F.EVENTID
) A
END
ELSE
BEGIN
---not linked resource group node have been removed. Therefore, need recalculate internal group node
UPDATE RGN
-- use event duration
SET RGN.DURATION = COALESCE(F.EVENTDURATION, 0) / 1000 - COALESCE(A.DURATION, 0)
FROM
APM.RESOURCEGROUPNODE RGN
JOIN #FILLINTERNALRESOURCESTABLE F ON F.EVENTID = RGN.EVENTID AND RGN.RESOURCEGROUPID = @INTERNALRESOURCEGROUPID
CROSS APPLY
(
SELECT
SUM(DURATION) DURATION
FROM
APM.RESOURCEGROUPNODE AS RGN2 (NOLOCK)
WHERE
RGN2.EVENTID = F.EVENTID
AND RGN2.RESOURCEGROUPID &lt;&gt; @INTERNALRESOURCEGROUPID
) A
END

-- create internal execution resources for event sources
EXEC APM.INSERTINTERNALRESOURCE

-- update resource and resource group node references for performance nodes
UPDATE P SET
P.RESOURCEID = R.RESOURCEID,
P.RESOURCEGROUPNODEID = RGN.RESOURCEGROUPNODEID,
P.RESOURCEMETHOD = R.RESOURCEURI,
P.SELFDURATION = P.DURATION
FROM
APM.PERFORMANCENODE P
JOIN #FILLINTERNALRESOURCESTABLE F ON F.EVENTID = P.EVENTID
JOIN APM.RESOURCEGROUPNODE RGN (NOLOCK) ON RGN.EVENTID = F.EVENTID AND RGN.RESOURCEGROUPID = @INTERNALRESOURCEGROUPID
JOIN APM.RESOURCE R (NOLOCK) ON R.RESOURCEURI = N'Internal Execution' AND R.SOURCEID = F.SOURCEID
WHERE P.RESOURCEID IS NULL

-- update resource reference on performance events
EXEC APM.UpdateEventsByInternalResource N'performance'
END

/* Processing exception nodes which are not have resources */
TRUNCATE TABLE #FILLINTERNALRESOURCESTABLE
INSERT INTO #FILLINTERNALRESOURCESTABLE(EVENTID,SOURCEID)
SELECT
E.EVENTID, E.SOURCEID
FROM
APM.EVENT (NOLOCK) E
WHERE
E.SEVIEWERDBID = @DATABASEID
AND E.EVENTID &gt;= @STARTID AND E.EVENTID &lt;= @ENDID
AND EXISTS(SELECT * FROM EXCEPTIONNODE Ex (NOLOCK) WHERE Ex.EVENTID = E.EVENTID AND Ex.RESOURCEID IS NULL)
AND E.EVENTCLASSTYPE = N'exception' OPTION(RECOMPILE)
IF (@@ROWCOUNT &gt; 0)
BEGIN
-- create internal execution resources for event sources
EXEC APM.INSERTINTERNALRESOURCE

-- update exception resource references
UPDATE EX
SET EX.RESOURCEID = R.RESOURCEID
FROM
APM.EXCEPTIONNODE EX
JOIN #FILLINTERNALRESOURCESTABLE F ON F.EVENTID = EX.EVENTID
JOIN APM.RESOURCE R (NOLOCK) ON R.RESOURCEURI = N'Internal Execution' AND R.SOURCEID = F.SOURCEID
END

/* Processing performance events which are not have resources */
TRUNCATE TABLE #FILLINTERNALRESOURCESTABLE
INSERT INTO #FILLINTERNALRESOURCESTABLE(EVENTID,SOURCEID)
SELECT
E.EVENTID,E.SOURCEID
FROM
APM.EVENT (NOLOCK) E
WHERE
E.SEVIEWERDBID = @DATABASEID
AND E.EVENTID &gt;= @STARTID AND E.EVENTID &lt;= @ENDID
AND (E.HEAVYLIGHT IS NULL OR E.HEAVYLIGHT &lt;&gt; 0)
AND E.RESOURCEID IS NULL
AND E.EVENTCLASSTYPE = N'performance' OPTION(RECOMPILE)
IF (@@ROWCOUNT &gt; 0)
-- update resource reference on performance events
EXEC APM.UpdateEventsByInternalResource N'performance'

/* Processing exception events which are not have resources */
TRUNCATE TABLE #FILLINTERNALRESOURCESTABLE
INSERT INTO #FILLINTERNALRESOURCESTABLE(EVENTID,SOURCEID)
SELECT
E.EVENTID,E.SOURCEID
FROM
APM.EVENT (NOLOCK) E
WHERE
E.SEVIEWERDBID = @DATABASEID
AND E.EVENTID &gt;= @STARTID AND E.EVENTID &lt;= @ENDID
AND E.RESOURCEID IS NULL
AND E.EVENTCLASSTYPE = N'exception' OPTION(RECOMPILE)
IF (@@ROWCOUNT &gt; 0)
-- update resource reference on exception events
EXEC APM.UpdateEventsByInternalResource N'exception'
END TRY
BEGIN CATCH
-- exception processing

-- check active transactions
IF (@@TRANCOUNT &gt; 0)
ROLLBACK TRAN

-- get context variables
SELECT
@ERRORNUMBER = ERROR_NUMBER()
,@ERRORSEVERITY = ERROR_SEVERITY()
,@ERRORSTATE = ERROR_STATE()
,@ERRORLINE = ERROR_LINE()
,@ERRORPROCEDURE = ISNULL(ERROR_PROCEDURE(), '-')
,@ERRORMESSAGETEXT = ERROR_MESSAGE()

-- switch error flag
SET @ERRORIND = 1
END CATCH

--report error if any
IF (@ERRORIND = 1)
BEGIN
DECLARE @ADJUSTEDERRORSEVERITY int

SET @ADJUSTEDERRORSEVERITY = CASE
WHEN @ERRORSEVERITY &gt; 18 THEN 18
ELSE @ERRORSEVERITY
END
SELECT @ERROR_MESSAGE = message FROM APM.Messages WHERE id = 50004
RAISERROR (@ERROR_MESSAGE, @ADJUSTEDERRORSEVERITY, 1
,@ERRORNUMBER
,@ERRORSEVERITY
,@ERRORSTATE
,@ERRORPROCEDURE
,@ERRORLINE
,@ERRORMESSAGETEXT
)
END
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.GetResource'), 'IsScalarFunction') IS NULL)
BEGIN
EXECUTE('CREATE FUNCTION APM.GetResource ()
RETURNS int
AS begin return 1 end')
END
GO
ALTER FUNCTION APM.GetResource (@METHOD nvarchar(255))
RETURNS nvarchar(255)
AS
BEGIN
RETURN
LEFT(
@METHOD,
CASE WHEN CHARINDEX(N'$', @METHOD) = 0 THEN LEN(@METHOD) ELSE CHARINDEX(N'$', @METHOD) - 1 END
)
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.GetResourceType'), 'IsScalarFunction') IS NULL)
BEGIN
EXECUTE('CREATE FUNCTION APM.GetResourceType ()
RETURNS int
AS begin return 1 end')
END
GO
ALTER FUNCTION [APM].[GetResourceType] (@RESOURCETYPE nvarchar(255))
RETURNS nvarchar(255)
AS
BEGIN
RETURN
CASE
WHEN @RESOURCETYPE LIKE N'Web%' OR @RESOURCETYPE LIKE N'WCF%' THEN N'WebService'
WHEN @RESOURCETYPE LIKE N'SQL%'
OR @RESOURCETYPE LIKE N'OLEDB%'
OR @RESOURCETYPE LIKE N'IBM DB2%'
OR @RESOURCETYPE LIKE N'Sybase%'
OR @RESOURCETYPE LIKE N'Query%'
OR @RESOURCETYPE LIKE N'ODBC%'
OR @RESOURCETYPE LIKE N'Oracle%'
OR @RESOURCETYPE LIKE N'ADOMD%'
THEN N'Database'
ELSE N'Internal'
END
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.ComputerResourceUtilization'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.ComputerResourceUtilization AS RETURN 1')
END
GO
/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: ComputerResourceUtilization */
/* USED IN: Computer resource utilization report */
/* INPUT PARAMETERS: */
/* @DATESTART - Start date of the priod */
/* @DATEEND - End date of the period */
/* @MACHINEIDS - List of machine Id, separated by comma. Exp: '4,5,6' */
/* @SORTORDER - Specifies field to which sorting should be applayed */
/* 1. CPU value */
/* 2. Memory value */
/* 3. I/O value */
/* 4. Request count */
/* @TOPROWCOUNT - defines number of top rows, which will be returned */
/************************************************************************************/

ALTER PROCEDURE APM.ComputerResourceUtilization
@DATESTART DateTime,
@DATEEND DateTime,
@MACHINEIDS NVARCHAR(MAX),
@SORTORDER INT,
@TOPROWCOUNT INT
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON

/****************************************************************************************/
/* ASSISTING TEMP TABLES */
/****************************************************************************************/
-- Filter table, which contains machine Ids
CREATE TABLE #COMPUTERPCOUNTERANALYSIS_FILTERTABLE
(
VALUEID INT
)
-- Split @MACHINEIDS and fill table with values from it
INSERT
INTO #COMPUTERPCOUNTERANALYSIS_FILTERTABLE
SELECT
CAST(p.value AS int)
FROM
APM.GetMultiParameters(@MACHINEIDS, N'') p

--Filter PerfHourly table for further manipulations
CREATE TABLE #COMPUTERPCOUNTERANALYSIS_PERFHOURLY
(
MACHINEID INT,
PCTYPE NVARCHAR(100) collate database_default,
SUMVALUE FLOAT,
MAXVALUE FLOAT,
SAMPLECOUNT BIGINT
)

INSERT
INTO #COMPUTERPCOUNTERANALYSIS_PERFHOURLY
SELECT
ph.MachineId AS MachineId,
t.type AS PCType,
ph.SumValue AS SumValue,
ph.MaxValue AS MaxValue,
ph.SampleCount AS SampleCount
FROM
APM.PerfHourly AS ph (NOLOCK)
JOIN APM.PCType AS t (NOLOCK) ON ph.PCTypeId = t.PCTypeId
JOIN #COMPUTERPCOUNTERANALYSIS_FILTERTABLE f ON ph.MachineId = f.VALUEID
WHERE
ph.UTCDate &gt;= @DATESTART
AND ph.UTCDate &lt; @DATEEND
AND ph.SourceId IS NULL
AND ph.PCProcessId IS NULL
AND t.Type IN (
N'\Processor\% Processor Time',
N'\Process\Private Bytes',
N'\Process\IO Data Bytes/sec',
N'\Apps\Monitored Requests')


/****************************************************************************************/
/* MAIN QUERY */
/****************************************************************************************/
;WITH ComputerResourceUtilization AS
(
SELECT
ph.MACHINEID,
AVG(CASE ph.PCTYPE WHEN N'\Processor\% Processor Time' THEN ph.SUMVALUE/SAMPLECOUNT END) AS ProcessorValue,
MAX(CASE ph.PCTYPE WHEN N'\Processor\% Processor Time' THEN ph.MAXVALUE END) AS MaxProcessorValue,
AVG(CASE ph.PCTYPE WHEN N'\Process\Private Bytes' THEN ph.SUMVALUE/SAMPLECOUNT END) AS MemoryValue,
MAX(CASE ph.PCTYPE WHEN N'\Process\Private Bytes' THEN ph.MAXVALUE END) AS MaxMemoryValue,
AVG(CASE ph.PCTYPE WHEN N'\Process\IO Data Bytes/sec' THEN ph.SUMVALUE/SAMPLECOUNT END) AS IOValue,
MAX(CASE ph.PCTYPE WHEN N'\Process\IO Data Bytes/sec' THEN ph.MAXVALUE END) AS MaxIOValue,
SUM(CASE ph.PCTYPE WHEN N'\Apps\Monitored Requests' THEN ph.SUMVALUE END) AS RequestValue
FROM
#COMPUTERPCOUNTERANALYSIS_PERFHOURLY AS ph
GROUP BY
ph.MACHINEID
),
OrderedDataSet AS
(
SELECT
ROW_NUMBER() OVER(ORDER BY
CASE @SORTORDER
WHEN 1 THEN cr.ProcessorValue
WHEN 2 THEN cr.MemoryValue
WHEN 3 THEN cr.IOValue
WHEN 4 THEN cr.RequestValue
END DESC
) AS Id,
m.Machine,
m.MachineId,
COALESCE(m.CPUCount, 1) AS CPUCount,
cr.ProcessorValue AS ProcessorValue,
cr.MaxProcessorValue AS MaxProcessorValue,
cr.MemoryValue/(1024*1024) AS MemoryValue,
cr.MaxMemoryValue/(1024*1024) AS MaxMemoryValue,
cr.IOValue/1024 AS IOValue,
cr.MaxIOValue/1024 AS MaxIOValue,
cr.RequestValue AS RequestValue,
-- Flag to define if cpu count is not null,
-- in case of CPUDefineFlag = 0, show warning message about it in report
COALESCE(m.CPUCount, 0) AS CPUDefineFlag
FROM
ComputerResourceUtilization AS cr
JOIN APM.Machine AS m (NOLOCK) ON m.MachineId = cr.MachineId
)
SELECT
*
FROM
OrderedDataSet
WHERE
Id &lt;= @TOPROWCOUNT
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.fn_nums'), 'IsTableFunction') IS NULL)
BEGIN
EXECUTE('CREATE FUNCTION APM.fn_nums() RETURNS TABLE
AS
RETURN
select clmn=1')
END
GO

ALTER FUNCTION APM.fn_nums(@N AS INT) RETURNS TABLE
AS
RETURN
WITH
L0 AS(SELECT 1 AS c UNION ALL SELECT 1),
L1 AS(SELECT 1 AS c FROM L0 AS A, L0 AS B),
L2 AS(SELECT 1 AS c FROM L1 AS A, L1 AS B),
L3 AS(SELECT 1 AS c FROM L2 AS A, L2 AS B),
L4 AS(SELECT 1 AS c FROM L3 AS A, L3 AS B),
L5 AS(SELECT 1 AS c FROM L4 AS A, L4 AS B),
Nums AS(SELECT ROW_NUMBER() OVER(ORDER BY c) AS n FROM L5)
SELECT n FROM Nums WHERE n &lt;= @N;
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.RemoveProcessIdFromName'), 'IsScalarFunction') IS NULL)
BEGIN
EXECUTE('CREATE FUNCTION APM.RemoveProcessIdFromName ()
RETURNS int
AS begin return 1 end')
END
GO
/************************************************************************************/
/* Object: Function */
/* Name: RemoveProcessIdFromName */
/* Returns: process name till # symbol. Exp: w3wp#1 -&gt; w3wp, w3wp -&gt; w3wp */
/* or process name till _ symbol. Exp: w3wp_123 -&gt; w3wp */
/* Parameters: */
/* @PROCESSNAME - Process name, from which #N will be removed */
/************************************************************************************/

ALTER FUNCTION APM.RemoveProcessIdFromName (@PROCESSNAME nvarchar(255))
RETURNS NVARCHAR(255)
AS
BEGIN
DECLARE @result nvarchar(255), @pos int

/* try to find w3wp#X instance formatting */
SET @pos = CHARINDEX(N'#', REVERSE(@PROCESSNAME))
SET @result = CASE WHEN @pos &gt; 0
THEN LEFT(@PROCESSNAME, LEN(@PROCESSNAME) - @pos)
ELSE @result END

/* if w3wp#X instance formatting is not found we will try */
/* to find w3wp_XXXX formatting */
IF @pos = 0
BEGIN
SET @pos = PATINDEX( '%[0-9][_]%', REVERSE(@PROCESSNAME))
SET @result = CASE WHEN @pos &gt; 0
THEN LEFT(@PROCESSNAME, LEN(@PROCESSNAME) - (@pos + 1))
ELSE @PROCESSNAME END
END

RETURN @result
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.ComputerResourceUtilizationBySource'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.ComputerResourceUtilizationBySource AS RETURN 1')
END
GO
/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: ComputerResourceUtilizationBySource */
/* USED IN: Computer resource utilization sub report */
/* INPUT PARAMETERS: */
/* @DATESTART - Start date of the priod */
/* @DATEEND - End date of the period */
/* @SOURCEIDS - List of the source id, separated by comma. Exp: '1,2,3' */
/* @MACHINEID - Machine Id for which data should be selected */
/* @SORTORDER - Specifies field to which sorting should be applayed */
/* 1. CPU value */
/* 2. Memory value */
/* 3. I/O value */
/* 4. Request count */
/************************************************************************************/

ALTER PROCEDURE APM.ComputerResourceUtilizationBySource
@DATESTART DATETIME,
@DATEEND DATETIME,
@SOURCEIDS NVARCHAR(MAX),
@MACHINEID NVARCHAR(255),
@SORTORDER INT
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON

/************************************************************************************/
/* PREPARE ASSISTING TEMP TABLES */
/************************************************************************************/

--Filter table, which contains source ids, transfered to SP in @SOURCEIDS parameter
CREATE TABLE #SOURCEPCOUNTERANALYSIS_FILTERTABLE(
VALUEID INT
)

-- Split computer ids list separated by comma and fill table with it
INSERT
INTO #SOURCEPCOUNTERANALYSIS_FILTERTABLE
SELECT
CAST(p.value AS INT)
FROM
--Splits incoming string. Uses comma as substring delimiter
APM.GetMultiParameters(@SOURCEIDS, N'') AS p

--Filter PerfHourly table to decrease records count fot further calcultaions
CREATE TABLE #PERFHOURLYBYMACHINE(
UTCDate DATETIME,
SOURCEID INT,
PCPROCESSID INT,
SUMVALUE FLOAT,
SAMPLECOUNT BIGINT,
PACKAGECOUNTER BIGINT,
MAXVALUE FLOAT,
TYPE NVARCHAR(MAX) collate database_default
)
INSERT INTO #PERFHOURLYBYMACHINE
SELECT
ph.UTCDate,
ph.sourceId,
ph.pcprocessId,
ph.SumValue,
ph.SampleCount,
ph.PackageCounter,
ph.MaxValue,
t.Type
FROM
APM.PerfHourly AS ph (NOLOCK)
JOIN APM.PCType AS t (NOLOCK) ON t.pctypeid = ph.pctypeid
WHERE
ph.UTCDate &gt;= @DATESTART
AND ph.UTCDate &lt; @DATEEND
AND ph.MachineId = @MACHINEID
AND t.type IN
(
N'\Process\% Processor Time',
N'\Process\IO Data Bytes/sec',
N'\Process\Private Bytes',
N'\Apps\Monitored Requests',
-- 'Processor% Processor Time' counter is taken to calculate application activity,
-- relative to hours, when machine had been sending counter
N'\Processor\% Processor Time'
)

--Assisting table for application pool forming
CREATE TABLE #PROCESSNAMEFORSOURCE(
SOURCE NVARCHAR(255) collate database_default,
SOURCEID INT,
EXTRAINFO NVARCHAR(MAX) collate database_default,
PROCESS NVARCHAR(255) collate database_default
)

--Insert source name with correspondent process name and extrainfo
INSERT INTO #PROCESSNAMEFORSOURCE
SELECT DISTINCT
S.Source,
ph.SOURCEID,
COALESCE(p.Extrainfo, N'') AS EXTRAINFO,
--Select process name till # symbol (w3wp#1 -&gt; w3wp, w3wp -&gt; w3wp)
APM.RemoveProcessIdFromName(p.Process) AS Process
FROM
#PERFHOURLYBYMACHINE AS ph
JOIN APM.Source AS s (NOLOCK) ON ph.SOURCEID = s.sourceId
JOIN APM.PCProcess AS p (NOLOCK) ON p.pcprocessId = ph.PCPROCESSID

/********************************************************************************/
/* MAIN QUERY */
/********************************************************************************/
--Get sources name, ids list separated by comma per app pool
;WITH AppPoolInfo AS
(
SELECT
c.EXTRAINFO,
c.PROCESS,
-- source names
(SELECT A.source AS [data()]
FROM
(
SELECT DISTINCT
N'''' + c1.SOURCE + N'''' + N',' AS source
FROM
#PROCESSNAMEFORSOURCE as c1
WHERE
c1.EXTRAINFO = c.EXTRAINFO
AND c1.PROCESS = c.PROCESS
) AS A
FOR XML PATH ('')
) AS AppPoolSources,
-- source ids
(SELECT A.sourceid AS [data()]
FROM
(
SELECT DISTINCT
CAST(c1.SOURCEID AS NVARCHAR) + N',' AS sourceid
FROM
#PROCESSNAMEFORSOURCE AS c1
WHERE
c1.EXTRAINFO = c.EXTRAINFO
AND c1.PROCESS = c.PROCESS
) AS A
FOR XML PATH ('')
) AS SourceIds
FROM
#PROCESSNAMEFORSOURCE AS c
JOIN #SOURCEPCOUNTERANALYSIS_FILTERTABLE AS f ON f.VALUEID = c.SOURCEID
GROUP BY
c.EXTRAINFO,
c.PROCESS
),
-- Filter sources for which data should be selected;
-- as info should be selected not only for transfered sources, but also for sources
-- in the same app pool
SourceFilter AS
(
--One application can be in the several app pools, so use DISTINCT
SELECT DISTINCT
s2.SOURCEID
FROM
#PROCESSNAMEFORSOURCE AS s1
JOIN #PROCESSNAMEFORSOURCE AS s2 ON s1.EXTRAINFO = s2.EXTRAINFO AND s1.PROCESS = s2.PROCESS
JOIN #SOURCEPCOUNTERANALYSIS_FILTERTABLE AS f ON s1.SOURCEID = f.VALUEID
),
--Filter PerfHourly by source
PerfHourlyBySource AS
(
SELECT
ph.UTCDate,
ph.PCPROCESSID,
ph.SUMVALUE,
ph.SAMPLECOUNT,
ph.PACKAGECOUNTER,
ph.MAXVALUE,
--This field is used for 'Apps\Monitored Requests' (this counter depends on source only, not process)
ph.SOURCEID,
ph.TYPE
FROM
#PERFHOURLYBYMACHINE AS ph (NOLOCK)
JOIN SourceFilter AS s ON s.SOURCEID = ph.SOURCEID
),
--Calculate resource utilization by process in one hour
ProcessHourlyResourceUtilization AS
(
SELECT
ph.UTCDate,
ph.pcprocessId,
ph.Type,
-- Select MAX value as in case of app pool, some of the application
-- could work only part of the hour, and the value should be taken for the
-- application worked for the longest period
MAX(ph.SumValue) AS SumValue,
MAX(ph.MaxValue) AS MaxValue,
MAX(ph.SampleCount) AS SampleCount,
MAX(ph.PackageCounter) AS PackageCounter
FROM
PerfHourlyBySource AS ph
WHERE
--This condition allows to exclude Monitored Requests counter
PCProcessId IS NOT NULL
GROUP BY
ph.UTCDate,
ph.pcprocessId,
ph.Type
),
--Calculate resource utilization by application in one hour
--application means - web application = AppPool, otherwise = processname
ApplicationHourlyResourceUtilization AS
(
SELECT
ph.UTCDate,
ph.Type,
SUM(ph.SampleCount)*1.0/MAX(ph.PackageCounter) AS InstanceCount,
--Select process name till # symbol
APM.RemoveProcessIdFromName(p.Process) AS ProcessName,
COALESCE(p.ExtraInfo, N'') AS ProcessExtraInfo,
SUM(SumValue)/SUM(SampleCount) AS AvgValue,
MAX(ph.MaxValue) AS MaxValue
FROM
ProcessHourlyResourceUtilization AS ph
JOIN APM.PCProcess AS p (NOLOCK) ON ph.PCProcessId = p.PCProcessId
GROUP BY
ph.UTCDate,
ph.Type,
APM.RemoveProcessIdFromName(p.Process),
p.ExtraInfo
),
--Calculate average application resource utilization over all specified period
ApplicationResourceUtilization AS
(
SELECT
ph.ProcessName,
ph.ProcessExtraInfo,
-- Number of hours when app was active
COUNT(DISTINCT ph.UTCDate) AS ApplicationAvailabilityHours,
-- Instance count should be same for different resource types in one hour for one process
-- and averaging them won't make any difference but allow to avoid one aggregation step
AVG(ph.InstanceCount) AS InstanceCount,
MAX(ph.InstanceCount) AS MaxInstanceCount,
AVG(CASE WHEN InstanceCount &lt; 1 THEN InstanceCount ELSE 1 END) AS AppActivity,
AVG(CASE WHEN ph.type = N'\Process\% Processor Time' THEN ph.AvgValue END) AS CPUAvgValue,
AVG(CASE WHEN ph.type = N'\Process\IO Data Bytes/sec' THEN ph.AvgValue END) AS IOAvgValue,
AVG(CASE WHEN ph.type = N'\Process\Private Bytes' THEN ph.AvgValue END) AS MemoryAvgValue,
MAX(CASE WHEN ph.type = N'\Process\% Processor Time' THEN ph.MaxValue END) AS CPUMaxValue,
MAX(CASE WHEN ph.type = N'\Process\IO Data Bytes/sec' THEN ph.MaxValue END) AS IOMaxValue,
MAX(CASE WHEN ph.type = N'\Process\Private Bytes' THEN ph.MaxValue END) AS MemoryMaxValue
FROM
ApplicationHourlyResourceUtilization AS ph
GROUP BY
ph.ProcessName,
ph.ProcessExtraInfo
),
--Count Monitored Requests for Application
ApplicationRequestCount AS
(
SELECT
c.EXTRAINFO,
c.PROCESS,
SUM(ph.SUMVALUE) AS RequestCount
FROM
PerfHourlyBySource AS ph
-- If source was running in several app pools
-- #PROCESSNAMEFORSOURCE would contain several rows for one sourceid.
-- In this case request count will be counted for all app pools
JOIN #PROCESSNAMEFORSOURCE AS c ON ph.SOURCEID = c.SOURCEID
WHERE
ph.type = N'\Apps\Monitored Requests'
GROUP BY
c.EXTRAINFO,
c.PROCESS
),
-- Count hours when computer sent counters.
-- This value is used to calculate application activity between hours
ComputerAvailabilityHours AS
(
SELECT
COUNT(DISTINCT ph.UTCDate) AS HoursCount
FROM
#PERFHOURLYBYMACHINE AS ph
WHERE
ph.SOURCEID IS NULL
AND ph.PCPROCESSID IS NULL
AND ph.TYPE = N'\Processor\% Processor Time'
),
OrderedDataSet AS
(
SELECT
ROW_NUMBER() OVER (ORDER BY
CASE @SORTORDER
WHEN 1 THEN res.CPUAvgValue
WHEN 2 THEN res.MemoryAvgValue
WHEN 3 THEN res.IOAvgValue
WHEN 4 THEN req.RequestCount
END DESC) AS Id,
b.ExtraInfo AS AppPoolName,
--Remove comma from the end
CASE b.AppPoolSources WHEN '' THEN '' ELSE LEFT(b.AppPoolSources, LEN(b.AppPoolSources)-1) END AS AppPoolSources,
-- SourceIds string is used for drillthrought report for transfering sources to it
b.SourceIds,
req.RequestCount,
-- Correct instance count and application activity with hours, when application was active
res.InstanceCount * (res.ApplicationAvailabilityHours*1.0/ca.HoursCount) AS InstanceCount,
res.MaxInstanceCount,
res.AppActivity * (res.ApplicationAvailabilityHours*1.0/ca.HoursCount) AS AppActivity,
-- Calculate resource utilization
res.CPUAvgValue/COALESCE(m.cpucount, 1) AS CPUAvgValue,
res.IOAvgValue/1024 AS IOAvgValue,
res.MemoryAvgValue/(1024*1024) AS MemoryAvgValue,
res.CPUMaxValue/COALESCE(m.cpucount, 1) AS CPUMaxValue,
res.IOMaxValue/1024 AS IOMaxValue,
res.MemoryMaxValue/(1024*1024) AS MemoryMaxValue,
-- This field used for chart value in subreport bottom,
-- and it should include application activity both for hour and for specified period (application availability),
-- in order to be consistan with computer resources
(CASE @SORTORDER
WHEN 1 THEN res.CPUAvgValue/COALESCE(m.cpucount, 1) * res.AppActivity * (res.ApplicationAvailabilityHours*1.0/ca.HoursCount)
WHEN 2 THEN res.MemoryAvgValue/(1024*1024) * res.AppActivity * (res.ApplicationAvailabilityHours*1.0/ca.HoursCount)
WHEN 3 THEN res.IOAvgValue/1024 * res.AppActivity * (res.ApplicationAvailabilityHours*1.0/ca.HoursCount)
WHEN 4 THEN req.RequestCount
END) AS OrderedValue
FROM
AppPoolInfo AS b
JOIN ApplicationResourceUtilization AS res ON res.ProcessExtraInfo = b.ExtraInfo AND res.ProcessName = b.Process
LEFT OUTER JOIN ApplicationRequestCount AS req ON req.ExtraInfo = b.ExtraInfo AND req.Process = b.Process
JOIN APM.Machine AS m (NOLOCK) ON m.machineid = @MACHINEID
-- This query has only one record, and this value is common for all sources,
-- so use CROSS JOIN
CROSS JOIN ComputerAvailabilityHours AS ca
)
SELECT
Id,
CASE
WHEN LEN(AppPoolName) &gt; 0 THEN AppPoolName + N' - '+ AppPoolSources
ELSE CASE AppPoolSources WHEN '' THEN '' ELSE SUBSTRING(AppPoolSources, 2, LEN(AppPoolSources)-2) END
END AS AppPoolName,
SourceIds,
RequestCount,
InstanceCount,
MaxInstanceCount,
AppActivity,
CPUAvgValue,
CPUMaxValue,
MemoryAvgValue,
MemoryMaxValue,
IOAvgValue,
IOMaxValue,
OrderedValue
FROM
OrderedDataSet
ORDER BY
Id
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.GetQueryDateCount'), 'IsScalarFunction') IS NULL)
BEGIN
EXECUTE('CREATE FUNCTION APM.GetQueryDateCount ()
RETURNS int
AS begin return 1 end')
END
GO
ALTER FUNCTION APM.GetQueryDateCount(@PERIODTYPE INT, @CURRENTDATE DATETIME) RETURNS INT
AS
BEGIN
RETURN
CASE @PERIODTYPE
WHEN 1 THEN 1
WHEN 2 THEN 7
WHEN 3 THEN 31
END
END
GO


--------------------End Helper function for the management_application_summary_quality_analysis_report ------------------


--------------------Helper function for the management_reports_breakdown_report ------------------

IF (OBJECTPROPERTY(OBJECT_ID('APM.GetDatePart'), 'IsScalarFunction') IS NULL)
BEGIN
EXECUTE('CREATE FUNCTION APM.GetDatePart ()
RETURNS int
AS begin return 1 end')
END
GO
alter FUNCTION APM.GetDatePart(@DATEPART nvarchar(10), @DATE dateTime) RETURNS INT
AS
BEGIN
RETURN
CASE @DATEPART
WHEN 'Hour' THEN Datepart(hh, @DATE)
WHEN 'WeekDay' THEN Datepart(dw, @DATE)
WHEN 'MonthDay' THEN Datepart(d, @DATE)
END
END
GO

-------------------End Helper function for the management_reports_breakdown_report-------------------

--------------------Temporary table----------------------
IF (OBJECTPROPERTY(OBJECT_ID('APM.DATES'), 'IsTable') IS NOT NULL)
BEGIN
DROP TABLE APM.DATES
END
GO
CREATE TABLE APM.DATES(
WeekDays smallint NULL,
HourDates smallint NULL,
MonthDays smallint NULL,
DatesId int NULL
)
GO

;WITH DATES_BUILD(WEEKDAYS,HOURDATES,MONTHDAYS, DatesId) AS
(
SELECT
CASE WHEN N &lt;= 7 THEN N END WEEKDAYS,
CASE WHEN N &lt;= 24 THEN N-1 END HOURDATES,
N AS MONTHDAYS,
N AS DatesId
FROM APM.FN_NUMS(31)
)
INSERT INTO APM.DATES SELECT * FROM DATES_BUILD
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.ApplicationResourceUtilization'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.ApplicationResourceUtilization AS RETURN 1')
END
GO
/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: ApplicationResourceUtilization */
/* USED IN: Application ResourceUtilization report */
/* INPUT PARAMETERS: */
/* @DATESTART - Start date of the priod */
/* @DATEEND - End date of the period */
/* @SOURCEIDS - List of source Id, separated by comma. Exp: '1,2,3' */
/* @MACHINEIDS - List of machine Id, separated by comma. Exp: '4,5,6' */
/* @SORTORDER - Specifies field to which sorting should be applayed */
/* 1. CPU value */
/* 2. Memory value */
/* 3. I/O value */
/* 4. Request count */
/* @TOPROWCOUNT - defines number of top rows, which will be returned */
/************************************************************************************/
ALTER PROCEDURE APM.ApplicationResourceUtilization
@DATESTART DATETIME,
@DATEEND DATETIME,
@SOURCEIDS NVARCHAR(MAX),
@MACHINEIDS NVARCHAR(MAX),
@SORTORDER INT,
@TOPROWCOUNT INT
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON

/****************************************************************************************/
/* ASSISTING TEMP TABLES */
/****************************************************************************************/

-- Filter table, which contains machine ids and source ids
-- typeid defines filter type - 1 for source and 2 for machine
-- valueId filter value - source id and machine id
CREATE TABLE #SOURCEMACHINEFILTERTABLE(
TYPEID INT,
VALUEID INT
)

-- Fill table #SOURCEMACHINEFILTERTABLE
INSERT
INTO #SOURCEMACHINEFILTERTABLE
SELECT
p.typeId AS TYPEID,
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@SOURCEIDS, @MACHINEIDS) AS p

-- Filter PerfHourly table to decrease nummber of rows for further manipulations.
-- Filtering by sources could not be done as some of the filtered sources can be in app pools,
-- so they should present in calculations
CREATE TABLE #PERFHOURLYFILTERBYMACHINE
(
UTCDate DATETIME,
SOURCEID INT,
MACHINEID INT,
PCPROCESSID INT,
SUMVALUE FLOAT,
SAMPLECOUNT BIGINT,
PACKAGECOUNTER BIGINT,
MAXVALUE FLOAT,
TYPE NVARCHAR(MAX) collate database_default
)

--Fill table #PERFHOURLYFILTERBYMACHINE
INSERT
INTO #PERFHOURLYFILTERBYMACHINE
SELECT
ph.UTCDate,
ph.sourceId,
ph.MachineId,
ph.pcprocessId,
ph.SumValue,
ph.SampleCount,
ph.PackageCounter,
ph.MaxValue,
t.Type
FROM
APM.PerfHourly AS ph (NOLOCK)
JOIN APM.PCType AS t (NOLOCK) ON t.pctypeid = ph.pctypeid
--Join with #SOURCEMACHINEFILTERTABLE provides filtering perfHourly by machineid
JOIN #SOURCEMACHINEFILTERTABLE AS f ON (f.TYPEID = 2 AND f.VALUEID = ph.MachineId)
WHERE
ph.UTCDate &gt;= @DATESTART
AND ph.UTCDate &lt; @DATEEND
AND t.type IN
(
N'\Process\% Processor Time',
N'\Process\IO Data Bytes/sec',
N'\Process\Private Bytes',
N'\Apps\Monitored Requests',
-- 'Processor% Processor Time' counter is taken to calculate application activity,
-- relative to hours, when machine sent counter
N'\Processor\% Processor Time'
)

--Assisting table for application pool forming
CREATE TABLE #PROCESSNAMEFORSOURCE(
SOURCE NVARCHAR(255) collate database_default,
SOURCEID INT,
MACHINEID INT,
EXTRAINFO NVARCHAR(MAX) collate database_default,
PROCESS NVARCHAR(255) collate database_default
)

-- Insert source and machine with correspondent process name and extrainfo
-- Here machine is used, as same source with same process name can run in different machines
INSERT INTO #PROCESSNAMEFORSOURCE
SELECT DISTINCT
S.Source,
ph.SOURCEID,
ph.MACHINEID,
COALESCE(p.Extrainfo, N'') AS EXTRAINFO,
--Select process name till # symbol (w3wp#1 -&gt; w3wp, w3wp -&gt; w3wp)
APM.RemoveProcessIdFromName(p.Process) AS Process
FROM
#PERFHOURLYFILTERBYMACHINE AS ph
JOIN APM.Source AS s (NOLOCK) ON ph.SOURCEID = s.sourceId
JOIN APM.PCProcess AS p (NOLOCK) ON p.pcprocessId = ph.PCPROCESSID

/********************************************************************************/
/* MAIN QUERY */
/********************************************************************************/
--Get sources name, ids list separated by comma per app pool
;WITH AppPoolInfo AS
(
SELECT
c.EXTRAINFO,
c.PROCESS,
c.MACHINEID,
-- all source names which have the same process name as passed in @SOURCEIDS
(SELECT A.source AS [data()]
FROM
(
SELECT DISTINCT
N'''' + c1.SOURCE + N'''' + N',' AS source
FROM
#PROCESSNAMEFORSOURCE AS c1
WHERE
c1.EXTRAINFO = c.EXTRAINFO
AND c1.PROCESS = c.PROCESS
AND c1.MACHINEID = c.MACHINEID
) AS A
FOR XML PATH ('')
) AS AppPoolSources,
--Select SourceIds list for application pool, this string is need to avoid drillthrought to other reports
(SELECT A.source AS [data()]
FROM
(
SELECT DISTINCT
CAST(c1.SOURCEID AS NVARCHAR(5)) + N',' AS source
FROM
#PROCESSNAMEFORSOURCE AS c1
WHERE
c1.EXTRAINFO = c.EXTRAINFO
AND c1.PROCESS = c.PROCESS
AND c1.MACHINEID = c.MACHINEID
) AS A
FOR XML PATH ('')
) AS SourceIds

FROM
#PROCESSNAMEFORSOURCE AS c
JOIN #SOURCEMACHINEFILTERTABLE AS f ON (f.TYPEID = 1 AND f.VALUEID = c.SOURCEID)
GROUP BY
c.EXTRAINFO,
c.PROCESS,
c.MACHINEID
),
-- Filter sources for which data should be selected;
-- as info should be selected not only for transfered sources, but also for sources
-- in the same app pool
SourceFilter AS
(
--One application can be in the several app pools, so use DISTINCT
SELECT DISTINCT
s2.SOURCEID
FROM
#PROCESSNAMEFORSOURCE AS s1
JOIN #PROCESSNAMEFORSOURCE AS s2 ON s1.EXTRAINFO = s2.EXTRAINFO AND s1.PROCESS = s2.PROCESS
JOIN #SOURCEMACHINEFILTERTABLE AS f ON (f.TYPEID = 1 AND s1.SOURCEID = f.VALUEID)
),
--Filter PerfHourly by source
PerfHourlyBySource AS
(
SELECT
ph.UTCDate,
ph.PCPROCESSID,
ph.MACHINEID,
ph.SUMVALUE,
ph.SAMPLECOUNT,
ph.PACKAGECOUNTER,
ph.MAXVALUE,
ph.SOURCEID,
ph.TYPE
FROM
#PERFHOURLYFILTERBYMACHINE AS ph (NOLOCK)
JOIN SourceFilter AS s ON s.SOURCEID = ph.SOURCEID
),
--Calculate resource utilization by processes on machines in one hour
ProcessHourlyResourceUtilization AS
(
SELECT
ph.MachineId,
ph.UTCDate,
ph.pcprocessId,
ph.Type,
-- Select MAX value as in case of app pool, some of the application
-- could work not whole hour, and the value should be taken for the
-- application worked for the longest period
MAX(ph.SumValue) AS SumValue,
MAX(ph.MaxValue) AS MaxValue,
MAX(ph.SampleCount) AS SampleCount,
MAX(ph.PackageCounter) AS PackageCounter
FROM
PerfHourlyBySource AS ph
WHERE
--This condition allows to exclude Monitored Requests counter
PCProcessId IS NOT NULL
GROUP BY
ph.MachineId,
ph.UTCDate,
ph.pcprocessId,
ph.Type
),
-- Calculate resource utilization by application in one hour.
-- Here "application" means - for web application = AppPool, otherwise = processname
ApplicationHourlyResourceUtilization AS
(
SELECT
ph.MachineId,
ph.UTCDate,
ph.Type,
SUM(ph.SampleCount)*1.0/MAX(ph.PackageCounter) AS InstanceCount,
--Select process name till # symbol
APM.RemoveProcessIdFromName(p.Process) AS ProcessName,
COALESCE(p.ExtraInfo, N'') AS ProcessExtraInfo,
SUM(SumValue)/SUM(SampleCount) AS AvgValue,
MAX(ph.MaxValue) AS MaxValue
FROM
ProcessHourlyResourceUtilization AS ph
JOIN APM.PCProcess AS p (NOLOCK) ON ph.PCProcessId = p.PCProcessId
GROUP BY
ph.MachineId,
ph.UTCDate,
ph.Type,
APM.RemoveProcessIdFromName(p.Process),
p.ExtraInfo
),
--Calculate average application resource utilization over all specified period per machine
ApplicationResourceUtilizationByMachines AS
(
SELECT
ph.MachineId,
ph.ProcessName,
ph.ProcessExtraInfo,
-- Number of hours when application was active
COUNT(DISTINCT ph.UTCDate) AS ApplicationAvailabilityHours,
-- Instance count should be same for different resource types in one hour for one process
-- and averaging them won't make any difference but allow to avoid one aggregation step
AVG(ph.InstanceCount) AS InstanceCount,
MAX(ph.InstanceCount) AS MaxInstanceCount,
AVG(CASE WHEN InstanceCount &lt; 1 THEN InstanceCount ELSE 1 END) AS AppActivity,
AVG(CASE WHEN ph.type = N'\Process\% Processor Time' THEN ph.AvgValue END) AS CPUAvgValue,
AVG(CASE WHEN ph.type = N'\Process\IO Data Bytes/sec' THEN ph.AvgValue END) AS IOAvgValue,
AVG(CASE WHEN ph.type = N'\Process\Private Bytes' THEN ph.AvgValue END) AS MemoryAvgValue,
MAX(CASE WHEN ph.type = N'\Process\% Processor Time' THEN ph.MaxValue END) AS CPUMaxValue,
MAX(CASE WHEN ph.type = N'\Process\IO Data Bytes/sec' THEN ph.MaxValue END) AS IOMaxValue,
MAX(CASE WHEN ph.type = N'\Process\Private Bytes' THEN ph.MaxValue END) AS MemoryMaxValue
FROM
ApplicationHourlyResourceUtilization AS ph
GROUP BY
ph.MachineId,
ph.ProcessName,
ph.ProcessExtraInfo
),
-- Count hours when computer sent counters.
-- This value is used to calculate application activity between hours
ComputerAvailabilityHours AS
(
SELECT
COUNT(DISTINCT ph.UTCDate) AS HoursCount,
ph.MACHINEID
FROM
#PERFHOURLYFILTERBYMACHINE AS ph
WHERE
ph.SOURCEID IS NULL
AND ph.PCPROCESSID IS NULL
AND ph.TYPE = N'\Processor\% Processor Time'
GROUP BY
ph.MACHINEID
),
-- Count Monitored Requests for Application on each machine
-- as source can run on different machines with same process name and app pool, but different sources set,
-- it is important to group by machine to, to avoid calculation of requests from the other app pool
ApplicationRequestCountByMachine AS
(
SELECT
ph.MACHINEID,
c.EXTRAINFO,
c.PROCESS,
SUM(ph.SUMVALUE) AS RequestCount
FROM
PerfHourlyBySource AS ph
-- If source was running in several app pools
-- #PROCESSNAMEFORSOURCE would contain several rows for one sourceid.
-- In this case request count will be counted for all app pools
JOIN #PROCESSNAMEFORSOURCE AS c ON (ph.SOURCEID = c.SOURCEID AND ph.MACHINEID = c.MACHINEID)
WHERE
ph.TYPE = N'\Apps\Monitored Requests'
GROUP BY
ph.MACHINEID,
c.EXTRAINFO,
c.PROCESS
),
--Summary application resource utilization info by machines
ApplicationResourceUtilization AS
(
SELECT
-- Enumerate computers within application by specified orderBy value
ROW_NUMBER() OVER (PARTITION BY
-- Application pool sources added to grouping as on different machines app pool with the same names
-- can contain different sources set, and app pools assumed to be same only
-- if its name and sources set are the same
appPool.ExtraInfo,
appPool.Process,
appPool.AppPoolSources
ORDER BY
CASE @SORTORDER
WHEN 1 THEN ph.CPUAvgValue/COALESCE(m.CPUCount, 1)
WHEN 2 THEN ph.MemoryAvgValue
WHEN 3 THEN ph.IOAvgValue
WHEN 4 THEN r.RequestCount
END DESC) AS ComputerId,
m.machine,
m.MachineId,
COALESCE(m.CpuCount, 1) AS CPUCount,
appPool.ExtraInfo,
appPool.Process,
-- Remove comma form the end of source list
CASE appPool.AppPoolSources WHEN '' THEN '' ELSE LEFT(appPool.AppPoolSources, LEN(appPool.AppPoolSources)-1) END AS AppPoolSources,
-- Use application activity during all period for instance count calculation and application activity
InstanceCount*ph.ApplicationAvailabilityHours*1.0/mc.HoursCount AS InstanceCount,
AppActivity*ph.ApplicationAvailabilityHours*1.0/mc.HoursCount AS AppActivity,
MaxInstanceCount AS MaxInstanceCount,
-- CPU load should be normalized on core count for each machine
CPUAvgValue/COALESCE(m.CPUCount, 1) AS CPUAvgValue,
CPUMaxValue/COALESCE(m.CPUCount, 1) AS CPUMaxValue,
IOAvgValue AS IOAvgValue,
IOMaxValue AS IOMaxValue,
MemoryAvgValue AS MemoryAvgValue,
MemoryMaxValue AS MemoryMaxValue,
r.RequestCount AS RequestCount,
appPool.SourceIds,
-- Flag to define if cpu count is not null,
-- in case of CPUDefineFlag = 0, show warning message about it in report
COALESCE(m.CPUCount, 0) AS CPUDefineFlag,
-- Calculate average value for SortBy field for application over all its machines
-- This value will be used to enumerate application by specified OrderBy Value
AVG(CASE @SORTORDER
WHEN 1 THEN ph.CPUAvgValue/COALESCE(m.CPUCount, 1)
WHEN 2 THEN ph.MemoryAvgValue
WHEN 3 THEN ph.IOAvgValue
END)
OVER (PARTITION BY appPool.ExtraInfo,
appPool.Process,
AppPoolSources ) AS OrderByValue,
-- For order by requests sum of requests should be calculated
SUM(r.RequestCount) OVER(PARTITION BY appPool.ExtraInfo,
appPool.Process,
AppPoolSources) AS ApplicationRequestCount
FROM
ApplicationResourceUtilizationByMachines AS ph
JOIN AppPoolInfo AS appPool ON (appPool.ExtraInfo = ph.ProcessExtraInfo AND
appPool.Process = ph.ProcessName AND
appPool.MachineId = ph.MachineId)
LEFT OUTER JOIN ApplicationRequestCountByMachine AS r ON (ph.ProcessName = r.Process
AND ph.ProcessExtraInfo = r.ExtraInfo
AND ph.MachineId = r.MachineId)
JOIN ComputerAvailabilityHours AS mc ON mc.MachineId = ph.MachineId
JOIN APM.Machine AS m (NOLOCK) ON m.MachineId = ph.MachineId
),
-- Value of Id field is duplicated for each application.
OrderedDataSet AS
(
SELECT
-- DENSE_RANK function returns equal id for equal values in Over expression
-- This allow to enumerate Application within result set by specified order by value
DENSE_RANK() OVER(ORDER BY
(CASE
WHEN @SORTORDER = 4 THEN ApplicationRequestCount
ELSE OrderByValue
END) DESC,
ExtraInfo,
AppPoolSources ) AS Id,
OrderByValue,
ComputerId,
machine,
MachineId,
CPUCount,
CASE
WHEN LEN(ExtraInfo) &gt; 0 THEN ExtraInfo + N' - '+ AppPoolSources
-- remove quotes from the start and end of the source name
ELSE CASE AppPoolSources WHEN '' THEN '' ELSE SUBSTRING(AppPoolSources, 2, LEN(AppPoolSources)-2) END
END AS AppPoolName,
CASE
WHEN LEN(ExtraInfo) &gt; 0 THEN ExtraInfo
ELSE CASE AppPoolSources WHEN '' THEN '' ELSE SUBSTRING(AppPoolSources, 2, LEN(AppPoolSources)-2) END
END AS ApplicationName,
InstanceCount,
MaxInstanceCount,
AppActivity,
CPUAvgValue,
CPUMaxValue,
IOAvgValue/1024 AS IOAvgValue,
IOMaxValue/1024 AS IOMaxValue,
MemoryAvgValue/(1024*1024) AS MemoryAvgValue,
MemoryMaxValue/(1024*1024) AS MemoryMaxValue,
RequestCount,
SourceIds,
CPUDefineFlag
FROM
ApplicationResourceUtilization
)
SELECT
*
FROM
OrderedDataSet
WHERE
Id &lt;= @TOPROWCOUNT
ORDER BY
Id
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.GetTop10MostFrequentFailureReport'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.GetTop10MostFrequentFailureReport AS RETURN 1')
END
GO
ALTER PROCEDURE APM.GetTop10MostFrequentFailureReport
@SOURCE NVARCHAR(MAX),
@COMPUTERS NVARCHAR(MAX),
@ENDDATE DATETIME,
@PERIOD INT,
@THRESHOLD INT,
@PROBLEM NVARCHAR(10),
@TIMEZONE INT,
@PMSTATUS NVARCHAR(50)
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON;

SET @ENDDATE = DATEADD(minute, -@TIMEZONE, @ENDDATE)

DECLARE @STARTDATE DATETIME
SET @STARTDATE = DATEADD(d, -APM.GetQueryDateCount(@PERIOD, @ENDDATE), @ENDDATE)

CREATE TABLE #GETTOP10MOSTFREQUENTFAILURE_SOURCEMACHINEMULTIVALUE
(
TYPEID int, VALUE int
)

INSERT
INTO #GETTOP10MOSTFREQUENTFAILURE_SOURCEMACHINEMULTIVALUE
SELECT
p.typeid,
cast(p.value AS Int)
FROM APM.GetMultiParameters(@SOURCE, @COMPUTERS) p

-- Filter table, which contains PM Statuses of Events
CREATE TABLE #PMSTATUSFILTERTABLE(
VALUEID INT
)

-- Fill table #PMSTATUSFILTERTABLE
INSERT
INTO #PMSTATUSFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@PMSTATUS, N'') AS p

DECLARE @LASTPERIODSTARTDATE DateTime
SET @LASTPERIODSTARTDATE = DATEADD(d, -APM.GetQueryDateCount(@PERIOD, @STARTDATE), @STARTDATE)

DECLARE @CURRENTPERIODENDDATE DateTime
SET @CURRENTPERIODENDDATE = DATEADD(d, APM.GetQueryDateCount(@PERIOD, @STARTDATE), @STARTDATE)


;WITH ExceptionProblems AS
(
SELECT
e.description,
e.category,
COUNT(
CASE
WHEN e.utceventdate &gt;= @STARTDATE AND e.utceventdate &lt; @CURRENTPERIODENDDATE
THEN e.eventid
END
) as EventsCount,
COUNT(
CASE
WHEN e.utceventdate &gt;= @LASTPERIODSTARTDATE AND e.utceventdate &lt; @STARTDATE
THEN e.eventid
END
) AS LastEventsCount,
MAX(e.SeViewerDBId) AS SeViewerDBId
FROM
APM.Event (NOLOCK) AS e
JOIN #GETTOP10MOSTFREQUENTFAILURE_SOURCEMACHINEMULTIVALUE AS f1 ON (f1.TYPEID = 1 AND e.sourceid = f1.VALUE)
JOIN #GETTOP10MOSTFREQUENTFAILURE_SOURCEMACHINEMULTIVALUE AS f2 ON (f2.TYPEID = 2 AND e.machineid = f2.VALUE)
JOIN #PMSTATUSFILTERTABLE AS f3 ON (f3.VALUEID = e.PMStatus)
WHERE
e.EventClassType = N'Exception'
AND (e.category LIKE @PROBLEM)
AND e.utceventdate &gt;= @LASTPERIODSTARTDATE
AND e.utceventdate &lt; @CURRENTPERIODENDDATE


GROUP BY
e.description, e.category
),
OrderedExceptionProblems AS
(
SELECT
ROW_NUMBER() OVER (ORDER BY EventsCount DESC) AS Id,
[description],
EventsCount,
LastEventsCount,
category,
db.[Address] AS SeViewer
FROM
ExceptionProblems AS e
JOIN APM.SeViewerDB AS db (NOLOCK) ON e.SeViewerDBId = db.SeViewerDBId
WHERE
EventsCount &gt; 0
),
GroupedExceptionProblems AS
(
SELECT
Id,
[description],
EventsCount,
LastEventsCount,
category,
SeViewer,
SUM(CASE WHEN Id &gt; 10 THEN EventsCount ELSE 0 END) OVER () AS OtherSum,
SUM(CASE WHEN Id &gt; 10 THEN LastEventsCount ELSE 0 END) OVER () AS OtherLastSum,
SUM(EventsCount) OVER () AS SummaryCount
FROM
OrderedExceptionProblems
)
SELECT
TOP 10 *
FROM
GroupedExceptionProblems ORDER BY Id
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.GetTop10MostFrequentPerformanceReport'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.GetTop10MostFrequentPerformanceReport AS RETURN 1')
END
GO
ALTER PROCEDURE APM.GetTop10MostFrequentPerformanceReport
@SOURCE NVARCHAR(MAX),
@COMPUTERS NVARCHAR(MAX),
@ENDDATE DATETIME,
@PERIOD INT,
@THRESHOLD INT,
@PROBLEM NVARCHAR(10),
@TIMEZONE INT,
@PMSTATUS NVARCHAR(50)
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON;

SET @ENDDATE = DATEADD(minute, -@TIMEZONE, @ENDDATE)

DECLARE @STARTDATE DateTime
SET @STARTDATE = DATEADD(d, -APM.GetQueryDateCount(@PERIOD, @ENDDATE), @ENDDATE)

DECLARE @LASTPERIODSTARTDATE DateTime
SET @LASTPERIODSTARTDATE = DATEADD(d, -APM.GetQueryDateCount(@PERIOD, @STARTDATE), @STARTDATE)

DECLARE @CURRENTPERIODENDDATE DateTime
SET @CURRENTPERIODENDDATE = DATEADD(d, APM.GetQueryDateCount(@PERIOD, @STARTDATE), @STARTDATE)

CREATE TABLE #GETTOP10MOSTFREQUENTPERFORMANCE_SOURCEMACHINEMULTIVALUE
(
TYPEID int, VALUE int
)
INSERT
INTO #GETTOP10MOSTFREQUENTPERFORMANCE_SOURCEMACHINEMULTIVALUE
SELECT
p.typeid,
cast(p.value AS Int)
FROM APM.GetMultiParameters(@SOURCE, @COMPUTERS) p

-- Filter table, which contains PM Statuses of Events
CREATE TABLE #PMSTATUSFILTERTABLE(
VALUEID INT
)

-- Fill table #PMSTATUSFILTERTABLE
INSERT
INTO #PMSTATUSFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@PMSTATUS, N'') AS p

CREATE INDEX idx_parametertmp ON #GETTOP10MOSTFREQUENTPERFORMANCE_SOURCEMACHINEMULTIVALUE(TYPEID) INCLUDE(VALUE)

;WITH PerformanceProblems AS
(
SELECT
COUNT(CASE WHEN e.utceventdate &gt;= @STARTDATE THEN e.eventid END) as IssuesCount,
AVG(CASE WHEN e.utceventdate &gt;= @STARTDATE THEN e.eventduration / 1000000 END) AS AvgDuration,
MAX(CASE WHEN e.utceventdate &gt;= @STARTDATE THEN e.eventduration / 1000000 END) AS MaxDuration,
COUNT(CASE WHEN e.utceventdate &lt; @STARTDATE THEN e.eventid END) AS LastIssuesCount,
e.rootnodename,
(CASE
WHEN pn.description IS NOT NULL THEN RIGHT(pn.description, LEN(pn.description) - CHARINDEX(':', pn.description))
ELSE N''
END) AS PerfNodeDescription
FROM
APM.Event (NOLOCK) AS e
JOIN #PMSTATUSFILTERTABLE AS f ON (f.VALUEID = e.PMStatus)
OUTER APPLY (
SELECT TOP(1)
description
FROM
APM.PerformanceNode (NOLOCK)
WHERE
EVENTID = e.EventId AND e.resourceid = resourceid
ORDER BY
SelfDuration DESC
) AS pn
WHERE
e.EventClassType = N'Performance' AND e.eventduration / 1000000.0 &gt;= @THRESHOLD
AND e.sourceid IN (SELECT VALUE FROM #GETTOP10MOSTFREQUENTPERFORMANCE_SOURCEMACHINEMULTIVALUE AS f1 WHERE f1.TYPEID = 1)
AND e.machineid IN (SELECT VALUE FROM #GETTOP10MOSTFREQUENTPERFORMANCE_SOURCEMACHINEMULTIVALUE AS f2 WHERE f2.TYPEID = 2)
AND (e.category LIKE @PROBLEM OR e.category IS NULL)
AND e.utceventdate &gt;= @LASTPERIODSTARTDATE
AND e.utceventdate &lt; @CURRENTPERIODENDDATE
AND (e.HeavyLight &lt;&gt; 0 OR e.HeavyLight IS NULL)


GROUP BY
e.rootnodename, (CASE
WHEN pn.description IS NOT NULL THEN RIGHT(pn.description, LEN(pn.description) - CHARINDEX(':', pn.description))
ELSE N''
END)
),
OrderedPerformanceProblems AS
(
SELECT
ROW_NUMBER() OVER (ORDER BY IssuesCount DESC) AS Id,
rootnodename,
PerfNodeDescription,
rootnodename + (CASE
WHEN LEN(PerfNodeDescription) &gt; 0
THEN ' slow at ' + PerfNodeDescription
ELSE N'' END) AS description,
IssuesCount,
AvgDuration,
MaxDuration,
LastIssuesCount,
(SELECT SUM(IssuesCount) FROM PerformanceProblems) AS SummaryCount
FROM
PerformanceProblems
WHERE
IssuesCount &gt; 0
),
GroupedPerformanceproblems AS
(
SELECT
Id,
rootnodename,
PerfNodeDescription,
description,
IssuesCount,
AvgDuration,
MaxDuration,
LastIssuesCount,
SUM(CASE WHEN Id &gt; 10 THEN IssuesCount ELSE 0 END) OVER () AS OtherSum,
SUM(CASE WHEN Id &gt; 10 THEN LastIssuesCount ELSE 0 END) OVER () AS OtherLastSum,
SUM(IssuesCount) OVER () AS SummaryCount
FROM
OrderedPerformanceProblems
)
SELECT
TOP(10) *
FROM
GroupedPerformanceproblems
ORDER BY
Id
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.GetTOP10NewExceptionProblems'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.GetTOP10NewExceptionProblems AS RETURN 1')
END
GO
ALTER PROCEDURE APM.GetTOP10NewExceptionProblems
@SOURCE NVARCHAR(MAX),
@COMPUTERS NVARCHAR(MAX),
@ENDDATE DATETIME,
@PERIOD INT,
@THRESHOLD INT,
@PROBLEM NVARCHAR(10),
@TIMEZONE INT
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON;

SET @ENDDATE = DATEADD(minute, -@TIMEZONE, @ENDDATE)

DECLARE @STARTDATE DATETIME
SET @STARTDATE = DATEADD(d, -APM.GetQueryDateCount(@PERIOD, @ENDDATE), @ENDDATE)

CREATE TABLE #GETTOP10NEWEXCEPTION_SOURCEMACHINEMULTIVALUE
(
TYPEID int, VALUE int
)
INSERT
INTO #GETTOP10NEWEXCEPTION_SOURCEMACHINEMULTIVALUE
SELECT
p.typeid,
cast(p.value AS Int)
FROM APM.GetMultiParameters(@SOURCE, @COMPUTERS) p

DECLARE @LASTPERIODSTARTDATE DateTime
SET @LASTPERIODSTARTDATE = DATEADD(d, -APM.GetQueryDateCount(@PERIOD, @STARTDATE), @STARTDATE)

DECLARE @CURRENTPERIODENDDATE DateTime
SET @CURRENTPERIODENDDATE = DATEADD(d, APM.GetQueryDateCount(@PERIOD, @STARTDATE), @STARTDATE)


;WITH NewExceptionProblems AS
(
SELECT
e.description,
e.category,
COUNT(DISTINCT e.eventid) as EventsCount,
MAX(e.SeViewerDBId) AS SeViewerDBId
FROM
APM.Event (NOLOCK) AS e
JOIN #GETTOP10NEWEXCEPTION_SOURCEMACHINEMULTIVALUE AS f1 ON (f1.VALUE = e.sourceid and f1.TYPEID = 1)
JOIN #GETTOP10NEWEXCEPTION_SOURCEMACHINEMULTIVALUE AS f2 ON (f2.VALUE = e.machineid and f2.TYPEID = 2)
JOIN APM.eventgroup (NOLOCK) AS eg ON e.eventGroupId = eg.EventGroupId
WHERE
e.EventClassType = N'Exception'
AND (e.category LIKE @PROBLEM)
AND e.utceventdate &gt;= @STARTDATE
AND e.utceventdate &lt; @CURRENTPERIODENDDATE
AND eg.firsteventdate &gt;= @STARTDATE
AND (e.PMStatus = 0)
GROUP BY
e.description, e.category
),
OrderedExceptionProblems AS
(
SELECT
ROW_NUMBER() OVER (ORDER BY EventsCount DESC) AS Id,
description,
EventsCount,
category,
db.Address AS SeViewer
FROM
NewExceptionProblems e
JOIN APM.SeViewerDB AS db (NOLOCK) ON e.SeViewerDBId = db.SeViewerDBId
),
GroupedExceptionProblems AS
(
SELECT
*,
SUM(CASE WHEN Id &gt; 10 THEN EventsCount ELSE 0 END) OVER() AS OtherSum,
SUM(EventsCount) OVER() AS EventsSum
FROM
OrderedExceptionProblems
)
SELECT
TOP 10 *
FROM
GroupedExceptionProblems
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.GetTOP10NewPerformanceProblems'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.GetTOP10NewPerformanceProblems AS RETURN 1')
END
GO
ALTER PROCEDURE APM.GetTOP10NewPerformanceProblems
@SOURCE NVARCHAR(MAX),
@COMPUTERS NVARCHAR(MAX),
@ENDDATE DATETIME,
@PERIOD INT,
@THRESHOLD INT,
@PROBLEM NVARCHAR(10),
@TIMEZONE INT
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON;

SET @ENDDATE = DATEADD(minute, -@TIMEZONE, @ENDDATE)

DECLARE @STARTDATE DATETIME
SET @STARTDATE = DATEADD(d, -APM.GetQueryDateCount(@PERIOD, @ENDDATE), @ENDDATE)

CREATE TABLE #GETTOP10NEWPERFORMANCE_SOURCEMACHINEMULTIVALUE
(
TYPEID int, VALUE int
)
INSERT
INTO #GETTOP10NEWPERFORMANCE_SOURCEMACHINEMULTIVALUE
SELECT
p.typeid,
cast(p.value AS Int)
FROM APM.GetMultiParameters(@SOURCE, @COMPUTERS) p

DECLARE @LASTPERIODSTARTDATE DateTime
SET @LASTPERIODSTARTDATE = DATEADD(d, -APM.GetQueryDateCount(@PERIOD, @STARTDATE), @STARTDATE)

DECLARE @CURRENTPERIODENDDATE DateTime
SET @CURRENTPERIODENDDATE = DATEADD(d, APM.GetQueryDateCount(@PERIOD, @STARTDATE), @STARTDATE)


;WITH NewPerformanceProblems AS
(
SELECT
COUNT(e.eventid) as IssuesCount,
AVG(e.eventduration / 1000000) AS AvgDuration,
MAX(e.eventduration / 1000000) AS MaxDuration,
e.rootnodename,
(CASE
WHEN pn.description IS NOT NULL THEN RIGHT(pn.description, LEN(pn.description) - CHARINDEX(':', pn.description))
ELSE N''
END) AS PerfNodeDescription
FROM
APM.Event AS e
JOIN #GETTOP10NEWPERFORMANCE_SOURCEMACHINEMULTIVALUE AS f1 ON (f1.VALUE = e.sourceid and f1.TYPEID = 1)
JOIN #GETTOP10NEWPERFORMANCE_SOURCEMACHINEMULTIVALUE AS f2 ON (f2.VALUE = e.machineid and f2.TYPEID = 2)
JOIN APM.eventgroup (NOLOCK) AS eg ON E.EventGroupId = eg.EventGroupId
OUTER APPLY (
SELECT TOP(1)
description
FROM
APM.PerformanceNode (NOLOCK)
WHERE
EVENTID = e.EventId AND e.resourceid = resourceid
ORDER BY
SelfDuration DESC
) AS pn
WHERE
e.EventClassType = N'Performance' AND e.eventduration / 1000000.0 &gt;= @THRESHOLD
AND (e.category LIKE @PROBLEM OR e.category IS NULL)
AND e.utceventdate &gt;= @STARTDATE
AND e.utceventdate &lt; @CURRENTPERIODENDDATE
AND eg.firsteventdate &gt;= @STARTDATE
AND eg.firsteventdate &lt; @CURRENTPERIODENDDATE
AND (e.HeavyLight &lt;&gt; 0 OR e.HeavyLight IS NULL)
AND (e.PMStatus = 0)
GROUP BY
e.rootnodename, (CASE
WHEN pn.description IS NOT NULL THEN RIGHT(pn.description, LEN(pn.description) - CHARINDEX(':', pn.description))
ELSE N''
END)
),
OrderedPerformanceProblems AS
(
SELECT
ROW_NUMBER() OVER (ORDER BY IssuesCount DESC) AS Id,
rootnodename,
PerfNodeDescription,
rootnodename + (CASE
WHEN LEN(PerfNodeDescription) &gt; 0
THEN ' slow at ' + PerfNodeDescription
ELSE N'' END) AS description,
IssuesCount,
AvgDuration,
MaxDuration
FROM
NewPerformanceProblems
),
GroupedPerformanceProblems AS
(
SELECT
*,
SUM(CASE WHEN Id &gt; 10 THEN IssuesCount ELSE 0 END) OVER() AS OtherSum,
SUM(IssuesCount) OVER() AS SummaryCount
FROM
OrderedPerformanceProblems
)
SELECT
TOP 10 *
FROM
GroupedPerformanceProblems
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.GetAbsDateByRelative'), 'IsScalarFunction') IS NULL)
BEGIN
EXECUTE('CREATE FUNCTION APM.GetAbsDateByRelative ()
RETURNS int
AS begin return 1 end')
END
GO
ALTER FUNCTION APM.GetAbsDateByRelative(@RELATIVEDATE INT) RETURNS DATETIME
AS
BEGIN
RETURN
CASE @RELATIVEDATE
WHEN 10 THEN DATEADD(d, -(DATEPART(WEEKDAY, GETDATE()) - 1), GETDATE())
WHEN 20 THEN DATEADD(d, (7 - DATEPART(WEEKDAY, GETDATE())), GETDATE())
WHEN 30 THEN DATEADD(WEEK, -1, DATEADD(d, -(DATEPART(WEEKDAY, GETDATE()) - 1), GETDATE()))
WHEN 40 THEN DATEADD(WEEK, -1, DATEADD(d, (7 - DATEPART(WEEKDAY, GETDATE())), GETDATE()))
WHEN 50 THEN DATEADD(DAY, -(DATEPART(DAY, GETDATE()) - 1), GETDATE())
WHEN 60 THEN DATEADD(d, -DATEPART(DAY, DATEADD(MONTH, 1, GETDATE())), DATEADD(MONTH, 1, GETDATE()))
WHEN 70 THEN DATEADD(MONTH, -1, DATEADD(DAY, -(DATEPART(DAY, GETDATE()) - 1), GETDATE()))
WHEN 80 THEN DATEADD(DAY, -DATEPART(DAY, GETDATE()), GETDATE())
WHEN 90 THEN GETDATE()
WHEN 100 THEN DATEADD(DAY, -1, GETDATE())
WHEN 110 THEN DATEADD(DAY, 1, GETDATE())
END
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('apm.Split'), 'IsTableFunction') IS NOT NULL)
BEGIN
DROP FUNCTION apm.Split
END
GO

CREATE FUNCTION apm.Split(@String NVARCHAR(MAX), @Delimiter NCHAR(1) = N',')
RETURNS @temptable TABLE
(
items NVARCHAR(MAX)
)
AS
BEGIN
DECLARE @idx INT
DECLARE @slice NVARCHAR(MAX)

SELECT @idx = 1

IF @Delimiter IS NULL OR LEN(@Delimiter) &lt; 1
return;

IF @String IS NULL OR LEN(@String) &lt; 1
return;

WHILE @idx!= 0
BEGIN
SET @idx = CHARINDEX(@Delimiter,@String)
IF @idx!=0
SET @slice = LEFT(@String,@idx - 1)
ELSE
SET @slice = @String

IF(LEN(@slice)&gt;0)
INSERT INTO @temptable(Items) VALUES(@slice)

SET @String = RIGHT(@String,LEN(@String) - @idx)
IF LEN(@String) = 0 BREAK
END
RETURN
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.GetMultiParameters'), 'IsTableFunction') IS NOT NULL)
BEGIN
DROP FUNCTION APM.GetMultiParameters
END
GO

create FUNCTION APM.GetMultiParameters(@PARAMETER1 NVARCHAR(MAX), @PARAMETER2 NVARCHAR(MAX))
RETURNS @RESULT TABLE
(
ID INT,
TYPEID INT,
VALUE NVARCHAR(MAX)
)
AS
BEGIN
;WITH Filters AS
(
SELECT
1 AS typeId, items AS [Value]
FROM
apm.Split(@PARAMETER1, ',')
UNION ALL
SELECT
2 AS typeId, items AS [Value]
FROM
apm.Split(@PARAMETER2, ',')
)
INSERT INTO @RESULT
SELECT
ROW_NUMBER() OVER (ORDER BY typeId, [Value]) AS Id,
typeId,
RTRIM(LTRIM([value])) AS Value
FROM
Filters

RETURN
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.ResourceUtilizationTrend'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.ResourceUtilizationTrend AS RETURN 1')
END
GO
/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: ResourceUtilizationTrend */
/* USED IN: Day of Week Utilization, Hour of Day Utilization, */
/* Utilization Trend reports */
/* INPUT PARAMETERS: */
/* @SOURCEIDS - List of source Id, separated by comma. Exp: '1,2,3' */
/* @MACHINEIDS - List of machine Id, separated by comma. Exp: '4,5,6' */
/* @STARTDATE - Start date of the priod */
/* @ENDDATE - End date of the period */
/* @TIMEZONE - Time offset relative to UTC. Used in SP to calculate */
/* period in UTC and for conversion UTC time back */
/* to user time (for showing in trend chart) */
/* @GROUPBY - Specifies result gouping type. Possible values: */
/* Hour - Group by hours. Rersult set will contain 24 rows */
/* corresponding to 24 hours. Date field - 0-23, Hour field - 0 */
/* WeekDay - Group by week days. For this grouping type extra grouping */
/* is applied - by hours. So result data set contains 7*24 rows. */
/* Date field values - 1-7, Hour fields - 0-23 */
/* Date - Group by date. Number of row equal to days count in specified*/
/* period. If extra parameter @GROUPBYHOUR = 1, then extra grouping*/
/* by hours applied. If @GROUPBYHOUR = 0, than date field values - */
/* 0-(@ENDDATE-@STARTDATE) and Hour field - 0.If @GROUPBYHOUR = 1*/
/* than date field values - 0-(@ENDDATE-@STARTDATE) */
/* and Hour field - 0-23 */
/* @GROUPBYHOUR - flag to apply extra grouping by Hour. Available only for */
/* grouping by Date. */
/************************************************************************************/
ALTER PROCEDURE APM.ResourceUtilizationTrend
@SOURCEIDS NVARCHAR(MAX),
@MACHINEIDS NVARCHAR(MAX),
@STARTDATE DATETIME,
@ENDDATE DATETIME,
@TIMEZONE INT,
@GROUPBY NVARCHAR(10),
@PMSTATUS NVARCHAR(50),
@GROUPBYHOUR BIT = 0
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON;
/************************************************************************************************************************/
/* DECLARE SP VARIABLES */
/************************************************************************************************************************/
--Convert start date to utc format
DECLARE @UTCSTARTDATE DATETIME
SET @UTCSTARTDATE = DATEADD(minute, -@TIMEZONE, @STARTDATE)

--Convert end date to utc format
DECLARE @UTCENDDATE DATETIME
SET @UTCENDDATE = DATEADD(minute, -@TIMEZONE, @ENDDATE)

-- Day count in specified period
DECLARE @PERIOD INT
SET @PERIOD = ABS(DATEDIFF(day, @STARTDATE, @ENDDATE)) + 1

-- Define if extra grouping by hours should be applied
DECLARE @DOGROUPINGBYHOUR BIT
SET @DOGROUPINGBYHOUR = CASE
-- For group by WeekDay always do extra grouping by hours, for grouping by Date, only if @GROUPBYHOUR = 1 specified
WHEN @GROUPBY = 'WeekDay' THEN 1
WHEN (@GROUPBY = 'Date' AND @GROUPBYHOUR = 1) THEN 1
ELSE 0
END

DECLARE @PROCESSORCOUNTERID INT
SELECT @PROCESSORCOUNTERID = PCtypeId FROM APM.PCType (NOLOCK) WHERE type = N'\Process\% Processor Time'

DECLARE @MEMORYCOUNTERID INT
SELECT @MEMORYCOUNTERID = PCtypeId FROM APM.PCType (NOLOCK) WHERE type = N'\Process\Private Bytes'

DECLARE @IOCOUNTERID INT
SELECT @IOCOUNTERID = PCtypeId FROM APM.PCType (NOLOCK) WHERE type = N'\Process\IO Data Bytes/sec'

DECLARE @MONITOREDREQUESTCOUNTERID INT
SELECT @MONITOREDREQUESTCOUNTERID = PCtypeId FROM APM.PCType (NOLOCK) WHERE type = N'\Apps\Monitored Requests'

DECLARE @REQUESTTIMECOUNTERID INT
SELECT @REQUESTTIMECOUNTERID = PCtypeId FROM APM.PCType (NOLOCK) WHERE type = N'\Apps\Avg. Request Time'

/************************************************************************************************************/
/* PREPARE ASSISTING TABLES */
/************************************************************************************************************/
-- Filter table, which contains machine ids and source ids
-- typeid defines filter type - 1 for source and 2 for machine
-- valueId filter value - source id and machine id
CREATE TABLE #RESOURCEUTILIZATIONTREND_SOURCEMACHINEFILTERTABLE(
TYPEID INT,
VALUEID INT
)

-- Fill table #RESOURCEUTILIZATIONTREND_SOURCEMACHINEFILTERTABLE
INSERT
INTO #RESOURCEUTILIZATIONTREND_SOURCEMACHINEFILTERTABLE
SELECT
p.typeId AS TYPEID,
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@SOURCEIDS, @MACHINEIDS) AS p

-- Filter table, which contains PM Statuses of Events
CREATE TABLE #PMSTATUSFILTERTABLE(
VALUEID INT
)

-- Fill table #PMSTATUSFILTERTABLE
INSERT
INTO #PMSTATUSFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@PMSTATUS, N'') AS p

--Assisting table for application pool forming
CREATE TABLE #PROCESSNAMEFORSOURCE(
SOURCE NVARCHAR(255) collate database_default,
SOURCEID INT,
MACHINEID INT,
EXTRAINFO NVARCHAR(MAX) collate database_default,
PROCESS NVARCHAR(255) collate database_default
)

-- Insert source and machine with correspondent process name and extrainfo
-- Here machine is used, as same source with same process name can run in different machines
INSERT INTO #PROCESSNAMEFORSOURCE
SELECT DISTINCT
S.Source,
ph.SourceId,
ph.MachineId,
COALESCE(p.Extrainfo, N'') AS EXTRAINFO,
--Select process name till # symbol (w3wp#1 -&gt; w3wp, w3wp -&gt; w3wp)
APM.RemoveProcessIdFromName(p.Process) AS Process
FROM
(
SELECT DISTINCT
ph.SourceId,
ph.pcprocessId,
ph.MachineId
FROM
APM.PerfHourly AS ph (NOLOCK)
WHERE
ph.pcprocessId IS NOT NULL
AND ph.UTCDate &gt;= @UTCSTARTDATE
AND ph.UTCDate &lt; @UTCENDDATE
) AS ph
JOIN APM.PCProcess AS p (NOLOCK) ON p.pcprocessId = ph.pcprocessId
JOIN APM.Source AS s (NOLOCK) ON s.SourceId = ph.SourceId
JOIN #RESOURCEUTILIZATIONTREND_SOURCEMACHINEFILTERTABLE AS f ON (f.TYPEID = 2 AND ph.MachineId = f.VALUEID)



-- Assisting table, which contains filtered rows from Event table
CREATE TABLE #EVENTFILTER
(
EVENTID BIGINT,
SOURCEID INT,
SEVIEWERADDRESS NVARCHAR(MAX) collate database_default,
HOUR INT,
DATE INT
)

INSERT INTO #EVENTFILTER
SELECT
e.EventId,
E.SourceId,
-- Select event SeViewerd address to provide link to it in report
db.Address AS SEVIEWERADDRESS,
-- If grouping by hour should be done, then get hour from event date, else - 0
-- Hour will be in user time, not in UTC
(CASE
WHEN @DOGROUPINGBYHOUR = 1
THEN DATEPART(hour, DATEADD(mi, @TIMEZONE, e.utceventdate))
ELSE 0
END) AS HOUR,
-- Get grouping date (for week day - week day number1-7, for hour day hour 0-23,
-- for date - number of days between event date and specified period start day 0-(@ENDDATE-@STARTDATE))
-- This information is in user time
(CASE
WHEN @GROUPBY = 'Date'
THEN ABS(DATEDIFF(d, @STARTDATE, DATEADD(minute, @TIMEZONE, e.utceventdate)))
ELSE APM.GetDatePart(@GROUPBY, DATEADD(mi, @TIMEZONE, e.utceventdate))
END) AS DATE
FROM
APM.EVENT AS e
JOIN APM.SeViewerDB AS db ON e.seviewerdbid = db.seviewerdbid
JOIN #RESOURCEUTILIZATIONTREND_SOURCEMACHINEFILTERTABLE f1 ON e.SourceId = f1.VALUEID AND f1.TYPEID = 1
JOIN #RESOURCEUTILIZATIONTREND_SOURCEMACHINEFILTERTABLE f2 ON e.MachineId = f2.VALUEID AND f2.TYPEID = 2
JOIN #PMSTATUSFILTERTABLE AS f3 ON (f3.VALUEID = e.PMStatus)
WHERE
e.UTCEventDate &gt;= @UTCSTARTDATE
AND e.UTCEventDate &lt; @UTCENDDATE
AND (e.HeavyLight IS NULL OR e.HeavyLight &gt; 0)


/********************************************************************************/
/* MAIN QUERY */
/********************************************************************************/
-- Get sources name, ids list separated by comma per app pool
-- This info should be selected for all sources, even they are in the same application pool
-- as in this report grouping by source is applied not by application pool.
;WITH AppPoolInfo AS
(
SELECT
c.EXTRAINFO,
c.PROCESS,
c.SOURCEID,
-- all source names which have the same process name as passed in @SOURCEIDS
(SELECT A.source AS [data()]
FROM
(
SELECT DISTINCT
N'''' + c1.SOURCE + N'''' + N',' AS source
FROM
#PROCESSNAMEFORSOURCE AS c1
WHERE
c1.EXTRAINFO = c.EXTRAINFO
AND c1.PROCESS = c.PROCESS
AND c1.MACHINEID = c.MACHINEID
) AS A
FOR XML PATH ('')
) AS AppPoolSources
FROM
#PROCESSNAMEFORSOURCE AS c
JOIN #RESOURCEUTILIZATIONTREND_SOURCEMACHINEFILTERTABLE AS f ON (f.TYPEID = 1 AND f.VALUEID = c.SOURCEID)
GROUP BY
c.EXTRAINFO,
c.PROCESS,
c.MACHINEID,
c.SOURCEID
),
SourceDescription AS (
SELECT DISTINCT
CASE
-- For web application add app pool name before source list (remove comma from the source list end)
WHEN LEN(pd.ExtraInfo) &gt; 0 THEN pd.ExtraInfo + CASE pd.AppPoolSources WHEN '' THEN '' ELSE ' (' + LEFT(pd.AppPoolSources, LEN(pd.AppPoolSources) - 1) + ')' END
-- For executable application remove quotes from the start and end and remove comma
ELSE CASE pd.AppPoolSources WHEN '' THEN '' ELSE SUBSTRING(pd.AppPoolSources, 2, LEN(pd.AppPoolSources)-3) END

END AppPool,
pd.SourceId
FROM
AppPoolInfo AS pd
),
-- Forms application pool list for each source
-- Format: AppPool1 - ('Source1', 'Source2', Source3), AppPool2 - ('Source1', 'Source4')
SourceAppPools AS (
SELECT
s.SourceId,
-- Also select source name, to show it to user in report
s.Source,
(SELECT a.AppPool AS [data()]
FROM
(
SELECT DISTINCT
sd.AppPool + N', ' AS AppPool
FROM
SourceDescription as sd
WHERE
sd.SourceId = s.Sourceid
) AS A
FOR XML PATH ('')
) AS AggAppPool
FROM
#RESOURCEUTILIZATIONTREND_SOURCEMACHINEFILTERTABLE AS f
JOIN APM.Source AS s (NOLOCK) ON f.VALUEID = s.SourceId
WHERE
f.TYPEID = 1
),
-- Report frame. It contains all sources, for which data sould be selected,
-- and date values accordingly to specified period and grouping type.
SourcesDates AS
(
SELECT DISTINCT
-- Remove comma from the end
CASE sd.AggAppPool WHEN '' THEN '' ELSE LEFT(sd.AggAppPool, LEN(sd.AggAppPool) - 1) END AS AppPool,
sd.Source AS Source,
sd.SourceId AS SourceId,
-- Decrease hours to one. Result either 0-23, or 0 (if grouping by hours not specified)
Hours.n-1 AS hours,
D.date AS date
FROM
SourceAppPools AS sd
-- If groupng by hours should be applied, select values for hours 1-24, else select only one value - 1
CROSS JOIN APM.fn_nums(
(CASE
WHEN @DOGROUPINGBYHOUR = 1 THEN 24
ELSE 1
END)) AS Hours
-- Select date, depending on Group by parameter
CROSS JOIN (SELECT
(CASE
-- Values 0-23
WHEN @GROUPBY = 'Hour' THEN n-1
-- Values 1-7
WHEN @GROUPBY = 'WeekDay' THEN n
-- Values 0 - (@ENDDATE - @STARTDATE)
WHEN @GROUPBY = 'Date' THEN n - 1
END) AS date
FROM
APM.fn_nums(
CASE
WHEN @GROUPBY = 'Hour' THEN 24
WHEN @GROUPBY = 'WeekDay' THEN 7
WHEN @GROUPBY = 'Date' THEN (@PERIOD)
END
)
) AS D
),
-- Calculate resource utilization by SOURCE in one hour.
-- Here counter values are aggregated between sources assosiated with app pool (process).
-- If source presents in several app pools, then in this step values from all of them will be aggregated
SourceHourlyResourceUtilization AS
(
SELECT
ph.MachineId,
-- Single source is a source for which information should be selected
-- Information about each process assosiated with single source and consolidated for it
ph.SourceId AS SingleSourceId,
ph.UTCDate,
ph.PCTypeId,
SUM(ph.SampleCount)*1.0/MAX(ph.PackageCounter) AS InstanceCount,
SUM(SumValue)/SUM(SampleCount) AS AvgValue
FROM
APM.PerfHourly AS ph (NOLOCK)
--Join with #RESOURCEUTILIZATIONTREND_SOURCEMACHINEFILTERTABLE provides filtering perfHourly by sourceid
JOIN #RESOURCEUTILIZATIONTREND_SOURCEMACHINEFILTERTABLE AS f1 ON (f1.TYPEID = 1 AND f1.VALUEID = ph.SourceId)
--Join with #RESOURCEUTILIZATIONTREND_SOURCEMACHINEFILTERTABLE provides filtering perfHourly by machineid
JOIN #RESOURCEUTILIZATIONTREND_SOURCEMACHINEFILTERTABLE AS f2 ON (f2.TYPEID = 2 AND f2.VALUEID = ph.MachineId)
WHERE
ph.UTCDate &gt;= @UTCSTARTDATE
AND ph.UTCDate &lt; @UTCENDDATE
AND PCTypeId IN (@PROCESSORCOUNTERID, @MEMORYCOUNTERID, @IOCOUNTERID)
GROUP BY
ph.MachineId,
ph.SourceId,
ph.UTCDate,
ph.PCTypeId
),
--Calculate average source resource utilization for each resource type
ApplicationResourceUtilizationByType AS
(
SELECT
ph.MachineId,
ph.SingleSourceId,
-- If grouping by hour should be done, then get hour from PCounter date, else - 0
-- Hour will be in user time, not in UTC
(CASE
WHEN @DOGROUPINGBYHOUR = 1
THEN DATEPART(hour, DATEADD(mi, @TIMEZONE, ph.utcdate))
ELSE 0
END) AS Hour,
-- Get grouping date (for week day - week day number1-7, for hour day hour 0-23,
-- for date - number of days between PCounter date and specified period start day 0-(@ENDDATE-@STARTDATE))
-- This information is in user time
(CASE
WHEN @GROUPBY = 'Date'
THEN ABS(DATEDIFF(d, @STARTDATE, DATEADD(minute, @TIMEZONE, ph.utcdate)))
ELSE APM.GetDatePart(@GROUPBY, DATEADD(mi, @TIMEZONE, ph.utcdate))
END) AS Date,
-- Instance count should be same for different resource types in one hour for one process
-- and averaging them won't make any difference but allow to avoid one aggregation step
AVG(ph.InstanceCount) AS InstanceCount,
AVG(CASE WHEN ph.PCTypeId = @PROCESSORCOUNTERID THEN ph.AvgValue END) AS CPUAvgValue,
AVG(CASE WHEN ph.PCTypeId = @IOCOUNTERID THEN ph.AvgValue END) AS IOAvgValue,
AVG(CASE WHEN ph.PCTypeId = @MEMORYCOUNTERID THEN ph.AvgValue END) AS MemoryAvgValue
FROM
SourceHourlyResourceUtilization AS ph
GROUP BY
ph.MachineId,
ph.SingleSourceId,
ph.utcdate
),
--Calculate average source resource utilization for specified grouping date
ApplicationResourceUtilizationByGroupingDate AS
(
SELECT
ph.MachineId,
ph.SingleSourceId,
ph.Hour,
ph.Date,
AVG(InstanceCount) AS InstanceCount,
AVG(CPUAvgValue) AS CPUAvgValue,
AVG(IOAvgValue) AS IOAvgValue,
AVG(MemoryAvgValue) AS MemoryAvgValue
FROM
ApplicationResourceUtilizationByType AS ph
GROUP BY
ph.MachineId,
ph.SingleSourceId,
ph.Hour,
ph.Date
),
-- Calculate average source resource utilization between machines
-- This aggregation is actual then grouping type is longer than specified period.
-- Exp: Group by week day, period - month. Then grouping between all mondays in this month should be applied
ApplicationResourceUtilizationBetweenMachines AS
(
SELECT
ph.SingleSourceId,
ph.Hour,
ph.Date,
AVG(InstanceCount) AS InstanceCount,
AVG(CPUAvgValue/COALESCE(m.CPUCount, 1)) AS CPUAvgValue,
AVG(IOAvgValue) AS IOAvgValue,
AVG(MemoryAvgValue) AS MemoryAvgValue
FROM
ApplicationResourceUtilizationByGroupingDate AS ph
JOIN APM.Machine AS m (NOLOCK) ON m.MachineId = ph.MachineId
GROUP BY
ph.SingleSourceId,
ph.Hour,
ph.Date
),
-- Monitored requests and request average time calculation by mechines with specified grouping
-- For this counter type perfhourly table contain one record for source, utcdate and machine, so other grouping is redundant
RequestsBySources AS
(
SELECT
ph.SourceId,
ph.MachineId,
SUM(CASE WHEN ph.PCTypeId = @MONITOREDREQUESTCOUNTERID THEN ph.SumValue END) AS ReqCount,
AVG(CASE WHEN ph.PCTypeId = @REQUESTTIMECOUNTERID THEN ph.SumValue/ph.SampleCount END) AS AvgReqTime,
-- If grouping by hour should be done, then get hour from PCounter date, else - 0
-- Hour will be in user time, not in UTC
(CASE
WHEN @DOGROUPINGBYHOUR = 1
THEN DATEPART(hour, DATEADD(mi, @TIMEZONE, ph.utcdate))
ELSE 0
END) AS Hour,
-- Get grouping date (for week day - week day number1-7, for hour day hour 0-23,
-- for date - number of days between PCounter date and specified period start day 0-(@ENDDATE-@STARTDATE))
-- This information is in user time
(CASE
WHEN @GROUPBY = 'Date'
THEN ABS(DATEDIFF(d, @STARTDATE, DATEADD(minute, @TIMEZONE, ph.utcdate)))
ELSE APM.GetDatePart(@GROUPBY, DATEADD(mi, @TIMEZONE, ph.utcdate))
END) AS Date
FROM
APM.PerfHourly AS ph (NOLOCK)
--Join with #RESOURCEUTILIZATIONTREND_SOURCEMACHINEFILTERTABLE provides filtering perfHourly by sourceid
JOIN #RESOURCEUTILIZATIONTREND_SOURCEMACHINEFILTERTABLE AS f1 ON (f1.TYPEID = 1 AND f1.VALUEID = ph.SourceId)
--Join with #RESOURCEUTILIZATIONTREND_SOURCEMACHINEFILTERTABLE provides filtering perfHourly by machineid
JOIN #RESOURCEUTILIZATIONTREND_SOURCEMACHINEFILTERTABLE AS f2 ON (f2.TYPEID = 2 AND f2.VALUEID = ph.MachineId)
WHERE
ph.UTCDate &gt;= @UTCSTARTDATE
AND ph.UTCDate &lt; @UTCENDDATE
AND ph.PCTypeId IN (@MONITOREDREQUESTCOUNTERID, @REQUESTTIMECOUNTERID)
GROUP BY
ph.SourceId,
ph.MachineId,
-- This aggregation is actual then grouping type is longer than specified perid.
-- Exp: Group by week day, period - month. Then grouping between all mondays in this month should be applied
(CASE
WHEN @DOGROUPINGBYHOUR = 1
THEN DATEPART(hour, DATEADD(mi, @TIMEZONE, ph.utcdate))
ELSE 0
END),
(CASE
WHEN @GROUPBY = 'Date'
THEN ABS(DATEDIFF(d, @STARTDATE, DATEADD(minute, @TIMEZONE, ph.utcdate)))
ELSE APM.GetDatePart(@GROUPBY, DATEADD(mi, @TIMEZONE, ph.utcdate))
END)
),
--Calculate request between machines
RequestsBetweenMachines AS
(
SELECT
SourceId,
SUM(ReqCount) AS ReqCount,
AVG(AvgReqTime) AS AvgReqTime,
Hour,
Date
FROM
RequestsBySources
GROUP BY
SourceId,
Hour,
Date
),
Events AS
(
SELECT
COUNT(e.EVENTID) AS EventCount,
MAX(e.SEVIEWERADDRESS) AS SeViewerAddress,
e.SOURCEID,
e.HOUR,
e.DATE
FROM
#EVENTFILTER AS e
GROUP BY
e.SOURCEID,
e.HOUR,
e.DATE
),
-- Check that CPU count is defined for all computers, where application run.
-- Computers set, where application run, does not depend on specified period by design, as otherwise there is performance problems
MachineCPUUndefinedFlag AS
(
SELECT
sf.SOURCEID,
MIN(COALESCE(m.CPUCount, -1)) AS CPUUndefinedFlag
FROM
#PROCESSNAMEFORSOURCE AS sf
JOIN APM.Machine AS m (NOLOCK) ON sf.MACHINEID = m.MachineId
GROUP BY
sf.SOURCEID
)
SELECT
sd.Date,
sd.Hours,
sd.AppPool AS ApplicationPool,
sd.SourceId,
sd.Source AS SingleSource,
E.SeViewerAddress,
COALESCE(pc.InstanceCount, 0) AS NumberOfApplicationInstances,
COALESCE(req.ReqCount, 0) AS NumberOfRequests,
COALESCE(req.AvgReqTime, 0) AS AverageRequestTime,
COALESCE(pc.CPUAvgValue, 0) AS ResourceCPUUsage,
COALESCE(pc.IOAvgValue, 0) AS ResourceIO,
COALESCE(pc.MemoryAvgValue, 0) AS ResourceMemory,
COALESCE(e.EventCount, 0) AS NumberOfEvents,
-- cpuFlag.CPUUndefinedFlag is null for current source if there is no one PCounter row
-- in PerfHourly table for specified period. If so, there is no need to show message about it
COALESCE(cpuFlag.CPUUndefinedFlag, 1) AS CPUUndefinedFlag
FROM
SourcesDates AS sd
LEFT OUTER JOIN MachineCPUUndefinedFlag AS cpuFlag ON sd.Sourceid = cpuFlag.Sourceid
LEFT OUTER JOIN ApplicationResourceUtilizationBetweenMachines AS pc ON (sd.SourceId = pc.SingleSourceId AND pc.Hour = sd.Hours AND pc.Date = sd.Date)
LEFT OUTER JOIN RequestsBetweenMachines AS req ON (sd.SourceId = req.SourceId AND req.Hour = sd.Hours AND req.Date = sd.Date)
LEFT OUTER JOIN Events AS e ON (sd.SourceId = e.SourceId AND e.Hour = sd.Hours AND e.Date = sd.Date)
ORDER BY
sd.SourceId,
sd.Date,
sd.Hours
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.Source_sync'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.Source_sync AS RETURN 1')
END
GO
----------------------------------Sync procedures----------------------------------

/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: Source_sync */
/* USED IN: Synchronization source table. Call by Intercept Reporting Services */
/* INPUT PARAMETERS: */
/* @OBJECTKEYXML - xml package syncronization data */
/* @TRACELEVEL - trace level. Reserved. */
/* OUTPUT PARAMETERS: */
/* @ROWNOTAFFECTED - number of records from package which haven't been */
/* synchronized.Reserved. */
/* Note: */
/* If there are records which have not been transferred that they have been already */
/* transferred from other SEVIEWER database earlier. Any other reason will cause a */
/* exception at an insert */
/************************************************************************************/
ALTER PROCEDURE APM.Source_sync
@OBJECTKEYXML ntext,
@TRACELEVEL int,
@ROWNOTAFFECTED int output
AS
BEGIN
SET NOCOUNT ON

DECLARE
@ERRORIND bit
,@ERRORMESSAGE nvarchar(max)
,@ERRORNUMBER int
,@ERRORSEVERITY int
,@ERRORSTATE int
,@ERRORLINE int
,@ERRORPROCEDURE nvarchar(256)
,@ERRORMESSAGETEXT nvarchar(max)

SET @ERRORIND = 0

BEGIN TRY

SET @ROWNOTAFFECTED = 0

DECLARE
@EXECRESULT int
,@XMLDOCHANDLE int
,@ERROR_MESSAGE nvarchar(max)

EXEC @EXECRESULT = sp_xml_preparedocument @XMLDOCHANDLE OUTPUT, @OBJECTKEYXML
IF @EXECRESULT &lt;&gt; 0
BEGIN
SELECT @ERROR_MESSAGE = message FROM APM.messages WHERE id = 50002
RAISERROR(@ERROR_MESSAGE, 16, 1, 'Source_sync', @EXECRESULT)
END

DECLARE @SOURCE TABLE (
source nvarchar(255) NOT NULL
)

----Fill table from package
INSERT @SOURCE (
source
)
SELECT
source
FROM OPENXML(@XMLDOCHANDLE, 'rows/row', 2) WITH (
source nvarchar(255) ) xml

EXEC sp_xml_removedocument @XMLDOCHANDLE

SET @XMLDOCHANDLE = NULL

--insert not existing
INSERT APM.source (source)
SELECT DISTINCT sync.source
FROM @SOURCE sync
WHERE NOT EXISTS (SELECT * FROM APM.source WHERE (source = sync.source))

END TRY
BEGIN CATCH
IF (@@TRANCOUNT &gt; 0)
ROLLBACK TRAN

SELECT
@ERRORNUMBER = ERROR_NUMBER()
,@ERRORSEVERITY = ERROR_SEVERITY()
,@ERRORSTATE = ERROR_STATE()
,@ERRORLINE = ERROR_LINE()
,@ERRORPROCEDURE = ISNULL(ERROR_PROCEDURE(), '-')
,@ERRORMESSAGETEXT = ERROR_MESSAGE()

SET @ERRORIND = 1
END CATCH

IF @XMLDOCHANDLE IS NOT NULL
EXEC sp_xml_removedocument @XMLDOCHANDLE

-- report error if any
IF (@ERRORIND = 1)
BEGIN
DECLARE @ADJUSTEDERRORSEVERITY int

SET @ADJUSTEDERRORSEVERITY = CASE
WHEN @ERRORSEVERITY = 2601 OR @ERRORSEVERITY = 2627 THEN 0
WHEN @ERRORSEVERITY &gt; 18 THEN 18
ELSE @ERRORSEVERITY
END

SELECT @ERROR_MESSAGE = message FROM APM.Messages WHERE id = 50004
RAISERROR (@ERROR_MESSAGE, @ADJUSTEDERRORSEVERITY, 1
,@ERRORNUMBER
,@ERRORSEVERITY
,@ERRORSTATE
,@ERRORPROCEDURE
,@ERRORLINE
,@ERRORMESSAGETEXT
)
END
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.Machine_sync'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.Machine_sync AS RETURN 1')
END
GO
/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: Machine_sync */
/* USED IN: Synchronization machine table. Call by Intercept Reporting Services */
/* INPUT PARAMETERS: */
/* @OBJECTKEYXML - xml package syncronization data */
/* @TRACELEVEL - trace level. Reserved. */
/* OUTPUT PARAMETERS: */
/* @ROWNOTAFFECTED - number of records from package which haven't been */
/* synchronized.Reserved. */
/* Note: */
/* If there are records which have not been transferred that they have been already */
/* transferred from other SEVIEWER database earlier. Any other reason will cause a */
/* exception at an insert */
/************************************************************************************/
ALTER PROCEDURE APM.Machine_sync
@OBJECTKEYXML ntext
,@TRACELEVEL int
,@ROWNOTAFFECTED int output
AS
BEGIN
SET NOCOUNT ON

DECLARE
@ERRORIND bit
,@ERRORMESSAGE nvarchar(max)
,@ERRORNUMBER int
,@ERRORSEVERITY int
,@ERRORSTATE int
,@ERRORLINE int
,@ERRORPROCEDURE nvarchar(256)
,@ERRORMESSAGETEXT nvarchar(max)

SET @ERRORIND = 0

BEGIN TRY

SET @ROWNOTAFFECTED = 0

DECLARE
@EXECRESULT int
,@XMLDOCHANDLE int
,@ERROR_MESSAGE nvarchar(max)

EXEC @EXECRESULT = sp_xml_preparedocument @XMLDOCHANDLE OUTPUT, @OBJECTKEYXML
IF @EXECRESULT &lt;&gt; 0
BEGIN
SELECT @ERROR_MESSAGE = message FROM APM.messages WHERE id = 50002
RAISERROR(@ERROR_MESSAGE, 16, 1, 'machine_sync', @EXECRESULT)
END

DECLARE @MACHINE TABLE (
machinename nvarchar(255)
,windowsversion nvarchar(50)
,agentversion nvarchar(50)
,cpucount int
)

----Fill table from package
INSERT @MACHINE (
machinename
,windowsversion
,agentversion
,cpucount
)
SELECT
machinename
,windowsversion
,agentversion
,cpucount
FROM OPENXML(@XMLDOCHANDLE, 'rows/row', 2) WITH (
machinename nvarchar(255)
,windowsversion nvarchar(50)
,agentversion nvarchar(50)
,cpucount int ) xml

EXEC sp_xml_removedocument @XMLDOCHANDLE

SET @XMLDOCHANDLE = NULL

/*------------------ sync machine--------------------*/

---update existing
UPDATE m
SET machine = sync.machinename
,windowsversion = sync.windowsversion
,agentversion = COALESCE(sync.agentversion, m.agentversion)
,cpucount = COALESCE(sync.cpucount, m.cpucount)
FROM APM.machine m
JOIN @MACHINE sync ON sync.machinename = m.machine

DECLARE @ALLAPPID int
DECLARE @NEWMACHINES TABLE (machineId int)

--insert not existing
INSERT APM.machine (machine, windowsversion, agentversion, cpucount) OUTPUT INSERTED.MACHINEID INTO @NEWMACHINES
SELECT DISTINCT sync.machinename, sync.windowsversion, sync.agentversion, sync.cpucount
FROM @MACHINE sync
WHERE NOT EXISTS (SELECT * FROM APM.machine WHERE (machine = sync.machinename))

IF EXISTS(SELECT * FROM @NEWMACHINES)
BEGIN
IF @ALLAPPID IS NULL
SELECT @ALLAPPID = APPLICATIONID FROM APM.APPLICATION (NOLOCK) WHERE APPLICATION = N'All'
---- it is need to create the links with 'All' application group for new sources
INSERT APM.APPLICATIONSOURCEMACHINE
( APPLICATIONID ,
SOURCEID ,
MACHINEID
)
SELECT
@ALLAPPID
,s.SourceId
,m.machineId
FROM
APM.SOURCE (NOLOCK) AS s
CROSS JOIN @NEWMACHINES as m
WHERE
NOT EXISTS
(
SELECT * FROM APM.APPLICATIONSOURCEMACHINE (NOLOCK) AS a
WHERE a.SOURCEID = s.sourceId AND a.APPLICATIONID = @ALLAPPID AND m.machineId = a.machineid
)
END
END TRY
BEGIN CATCH
IF (@@TRANCOUNT &gt; 0)
ROLLBACK TRAN

SELECT
@ERRORNUMBER = ERROR_NUMBER()
,@ERRORSEVERITY = ERROR_SEVERITY()
,@ERRORSTATE = ERROR_STATE()
,@ERRORLINE = ERROR_LINE()
,@ERRORPROCEDURE = ISNULL(ERROR_PROCEDURE(), '-')
,@ERRORMESSAGETEXT = ERROR_MESSAGE()

SET @ERRORIND = 1
END CATCH

IF @XMLDOCHANDLE IS NOT NULL
EXEC sp_xml_removedocument @XMLDOCHANDLE

-- report error if any
IF (@ERRORIND = 1)
BEGIN
DECLARE @ADJUSTEDERRORSEVERITY int

SET @ADJUSTEDERRORSEVERITY = CASE
WHEN @ERRORSEVERITY = 2601 OR @ERRORSEVERITY = 2627 THEN 0
WHEN @ERRORSEVERITY &gt; 18 THEN 18
ELSE @ERRORSEVERITY
END

SELECT @ERROR_MESSAGE = message FROM APM.Messages WHERE id = 50004
RAISERROR (@ERROR_MESSAGE, @ADJUSTEDERRORSEVERITY, 1
,@ERRORNUMBER
,@ERRORSEVERITY
,@ERRORSTATE
,@ERRORPROCEDURE
,@ERRORLINE
,@ERRORMESSAGETEXT
)
END
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.PCType_sync'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.PCType_sync AS RETURN 1')
END
GO
/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: PCType_sync */
/* USED IN: Synchronization pctype table. Call by Intercept Reporting Services */
/* INPUT PARAMETERS: */
/* @OBJECTKEYXML - xml package syncronization data */
/* @TRACELEVEL - trace level. Reserved. */
/* OUTPUT PARAMETERS: */
/* @ROWNOTAFFECTED - number of records from package which haven't been */
/* synchronized.Reserved. */
/* Note: */
/* If there are records which have not been transferred that they have been already */
/* transferred from other SEVIEWER database earlier. Any other reason will cause a */
/* exception at an insert */
/************************************************************************************/
ALTER PROCEDURE APM.PCType_sync
@OBJECTKEYXML ntext,
@TRACELEVEL int,
@ROWNOTAFFECTED int output
AS
BEGIN
SET NOCOUNT ON

DECLARE
@ERRORIND bit
,@ERRORMESSAGE nvarchar(max)
,@ERRORNUMBER int
,@ERRORSEVERITY int
,@ERRORSTATE int
,@ERRORLINE int
,@ERRORPROCEDURE nvarchar(256)
,@ERRORMESSAGETEXT nvarchar(max)

SET @ERRORIND = 0

BEGIN TRY

SET @ROWNOTAFFECTED = 0

DECLARE
@EXECRESULT int
,@XMLDOCHANDLE int
,@ERROR_MESSAGE nvarchar(max)

EXEC @EXECRESULT = sp_xml_preparedocument @XMLDOCHANDLE OUTPUT, @OBJECTKEYXML
IF @EXECRESULT &lt;&gt; 0
BEGIN
SELECT @ERROR_MESSAGE = message FROM APM.messages WHERE id = 50002
RAISERROR(@ERROR_MESSAGE, 16, 1, 'PCType_sync', @EXECRESULT)
END

DECLARE @PCTYPE TABLE (
type nvarchar(255) collate database_default
,measure nvarchar(50) collate database_default
)

----Fill table from package
INSERT @PCTYPE (
type
,measure
)
SELECT
type
,measure
FROM OPENXML(@XMLDOCHANDLE, 'rows/row', 2) WITH (
type nvarchar(255)
,measure nvarchar(50) ) xml

EXEC sp_xml_removedocument @XMLDOCHANDLE

SET @XMLDOCHANDLE = NULL

--------------sync type---------
UPDATE T
SET Type = sync.type, measure = sync.measure
FROM APM.pctype T
JOIN @PCTYPE sync ON sync.type = T.Type

INSERT APM.pctype (type, measure)
SELECT DISTINCT sync.type, sync.measure
FROM @PCTYPE sync
WHERE NOT EXISTS (SELECT * FROM APM.PCType WHERE (type = sync.type))
END TRY
BEGIN CATCH
IF (@@TRANCOUNT &gt; 0)
ROLLBACK TRAN

SELECT
@ERRORNUMBER = ERROR_NUMBER()
,@ERRORSEVERITY = ERROR_SEVERITY()
,@ERRORSTATE = ERROR_STATE()
,@ERRORLINE = ERROR_LINE()
,@ERRORPROCEDURE = ISNULL(ERROR_PROCEDURE(), '-')
,@ERRORMESSAGETEXT = ERROR_MESSAGE()

SET @ERRORIND = 1
END CATCH

IF @XMLDOCHANDLE IS NOT NULL
EXEC sp_xml_removedocument @XMLDOCHANDLE

-- report error if any
IF (@ERRORIND = 1)
BEGIN
DECLARE @ADJUSTEDERRORSEVERITY int

SET @ADJUSTEDERRORSEVERITY = CASE
WHEN @ERRORSEVERITY = 2601 OR @ERRORSEVERITY = 2627 THEN 0
WHEN @ERRORSEVERITY &gt; 18 THEN 18
ELSE @ERRORSEVERITY
END

SELECT @ERROR_MESSAGE = message FROM APM.Messages WHERE id = 50004
RAISERROR (@ERROR_MESSAGE, @ADJUSTEDERRORSEVERITY, 1
,@ERRORNUMBER
,@ERRORSEVERITY
,@ERRORSTATE
,@ERRORPROCEDURE
,@ERRORLINE
,@ERRORMESSAGETEXT
)
END
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.Aspect_sync'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.Aspect_sync AS RETURN 1')
END
GO
/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: Aspect_sync */
/* USED IN: Synchronization aspect table. Call by Intercept Reporting Services */
/* INPUT PARAMETERS: */
/* @OBJECTKEYXML - xml package syncronization data */
/* @TRACELEVEL - trace level. Reserved. */
/* OUTPUT PARAMETERS: */
/* @ROWNOTAFFECTED - number of records from package which haven't been */
/* synchronized.Reserved. */
/* Note: */
/* If there are records which have not been transferred that they have been already */
/* transferred from other SEVIEWER database earlier. Any other reason will cause a */
/* exception at an insert */
/************************************************************************************/
ALTER PROCEDURE APM.Aspect_sync
@OBJECTKEYXML ntext
,@TRACELEVEL int
,@ROWNOTAFFECTED int output
AS
BEGIN
SET NOCOUNT ON

DECLARE
@ERRORIND bit
,@ERRORMESSAGE nvarchar(max)
,@ERRORNUMBER int
,@ERRORSEVERITY int
,@ERRORSTATE int
,@ERRORLINE int
,@ERRORPROCEDURE nvarchar(256)
,@ERRORMESSAGETEXT nvarchar(max)

SET @ERRORIND = 0

BEGIN TRY

DECLARE
@EXECRESULT int
,@XMLDOCHANDLE int
,@ERROR_MESSAGE nvarchar(max)

SET @ROWNOTAFFECTED = 0

EXEC @EXECRESULT = sp_xml_preparedocument @XMLDOCHANDLE OUTPUT, @OBJECTKEYXML
IF @EXECRESULT &lt;&gt; 0
BEGIN
SELECT @ERROR_MESSAGE = message FROM APM.messages WHERE id = 50002
RAISERROR(@ERROR_MESSAGE, 16, 1, 'Aspect_sync', @EXECRESULT)
END

DECLARE @ASPECT TABLE (
Aspect nvarchar(50) collate database_default NOT NULL
,Description nvarchar(255) collate database_default NULL
)

----Fill table from package
INSERT @ASPECT (
Aspect
,Description
)
SELECT
Aspect
,Description
FROM OPENXML(@XMLDOCHANDLE, 'rows/row', 2) WITH (
aspect nvarchar(50)
,description nvarchar(256) ) xml

EXEC sp_xml_removedocument @XMLDOCHANDLE

SET @XMLDOCHANDLE = NULL

---update existing
UPDATE asp
SET Aspect = sync.Aspect, Description = sync.Description
FROM APM.Aspect asp
JOIN @ASPECT sync ON sync.Aspect = asp.aspect

--insert not existing
INSERT APM.aspect (aspect, description)
SELECT DISTINCT sync.Aspect, sync.Description
FROM @ASPECT sync
WHERE NOT EXISTS (SELECT * FROM APM.Aspect WHERE (aspect = sync.Aspect))
END TRY
BEGIN CATCH
IF (@@TRANCOUNT &gt; 0)
ROLLBACK TRAN

SELECT
@ERRORNUMBER = ERROR_NUMBER()
,@ERRORSEVERITY = ERROR_SEVERITY()
,@ERRORSTATE = ERROR_STATE()
,@ERRORLINE = ERROR_LINE()
,@ERRORPROCEDURE = ISNULL(ERROR_PROCEDURE(), '-')
,@ERRORMESSAGETEXT = ERROR_MESSAGE()
SET @ERRORIND = 1
END CATCH

IF @XMLDOCHANDLE IS NOT NULL
EXEC sp_xml_removedocument @XMLDOCHANDLE

-- report error if any
IF (@ERRORIND = 1)
BEGIN
DECLARE @ADJUSTEDERRORSEVERITY int

SET @ADJUSTEDERRORSEVERITY = CASE
WHEN @ERRORSEVERITY = 2601 OR @ERRORSEVERITY = 2627 THEN 0
WHEN @ERRORSEVERITY &gt; 18 THEN 18
ELSE @ERRORSEVERITY
END
SELECT @ERROR_MESSAGE = message FROM APM.Messages WHERE id = 50004

RAISERROR (@ERROR_MESSAGE, @ADJUSTEDERRORSEVERITY, 1
,@ERRORNUMBER
,@ERRORSEVERITY
,@ERRORSTATE
,@ERRORPROCEDURE
,@ERRORLINE
,@ERRORMESSAGETEXT
)
END
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.EventGroup_sync'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.EventGroup_sync AS RETURN 1')
END
GO
/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: EventGroup_sync */
/* USED IN: Synchronization eventgroup and cseventgroup tables. */
/* Call by Intercept Reporting Services */
/* INPUT PARAMETERS: */
/* @OBJECTKEYXML - xml package syncronization data */
/* @TRACELEVEL - trace level. Reserved. */
/* OUTPUT PARAMETERS: */
/* @ROWNOTAFFECTED - number of records from package which haven't been */
/* synchronized. */
/************************************************************************************/
ALTER PROCEDURE [APM].[EventGroup_sync]
@OBJECTKEYXML ntext
,@TRACELEVEL int
,@ROWNOTAFFECTED int output
AS
BEGIN
SET NOCOUNT ON

DECLARE
@ERRORIND bit
,@ERRORMESSAGE nvarchar(max)
,@ERRORNUMBER int
,@ERRORSEVERITY int
,@ERRORSTATE int
,@ERRORLINE int
,@ERRORPROCEDURE nvarchar(256)
,@ERRORMESSAGETEXT nvarchar(max)

SET @ERRORIND = 0

BEGIN TRY

DECLARE
@EXECRESULT int
,@XMLDOCHANDLE int
,@ERROR_MESSAGE nvarchar(max)
,@UPDATED_ROWCOUNT int
,@INSERTED_ROWCOUNT int
,@CHANGED_ROWCOUNT int
,@MESSAGE nvarchar(max)

SET @ROWNOTAFFECTED = 0

EXEC @EXECRESULT = sp_xml_preparedocument @XMLDOCHANDLE OUTPUT, @OBJECTKEYXML
IF @EXECRESULT &lt;&gt; 0
BEGIN
SELECT @ERROR_MESSAGE = message FROM APM.messages WHERE id = 50002
RAISERROR(@ERROR_MESSAGE, 16, 1, 'EventGroup_sync', @EXECRESULT)
END

DECLARE @EVENTGROUP TABLE (
id int identity(1,1)
,source nvarchar(255) collate database_default
,firsteventdate datetime
,lasteventdate datetime
,eventclasstype nvarchar(50) collate database_default
,rootnodename nvarchar(255) collate database_default
,aspect nvarchar(50) collate database_default
,hashvalue nvarchar(50) collate database_default
,client bit
,description nvarchar(max) collate database_default
,sourceid int
)

--Fill temporary table from package
INSERT @EVENTGROUP (
source
,firsteventdate
,lasteventdate
,eventclasstype
,rootnodename
,aspect
,hashvalue
,client
,description
)
SELECT DISTINCT
source
,firsteventdate
,lasteventdate
,eventclasstype
,rootnodename
,aspect
,hashvalue
,CASE WHEN source LIKE '%(Client)' THEN 1 ELSE 0 END
,description
FROM OPENXML(@XMLDOCHANDLE, 'rows/row', 2) WITH (
source nvarchar(255)
,firsteventdate datetime
,lasteventdate datetime
,eventclasstype nvarchar(50)
,rootnodename nvarchar(255)
,aspect nvarchar(50)
,hashvalue nvarchar(50)
,description nvarchar(max)
) xml

EXEC sp_xml_removedocument @XMLDOCHANDLE

SET @XMLDOCHANDLE = NULL

--remove duplicates by hashvalue
Delete g1
from @EVENTGROUP g1
join @EVENTGROUP g2 on g1.id &gt; g2.id and g1.hashvalue = g2.hashvalue



----- sources can be removed using "Remove applications wizard" so it is need synchronize sources ----
DECLARE @NEWSOURCES TABLE (sourceid int)

INSERT APM.SOURCE (SOURCE) OUTPUT INSERTED.SOURCEID INTO @NEWSOURCES
SELECT DISTINCT source FROM @EVENTGROUP eg
WHERE NOT EXISTS (SELECT * FROM APM.source s (NOLOCK) WHERE s.source = eg.source)
IF EXISTS(SELECT * FROM @NEWSOURCES)
BEGIN
DECLARE @ALLAPPID int
SELECT @ALLAPPID = APPLICATIONID FROM APM.APPLICATION (NOLOCK) WHERE APPLICATION = N'All'
---- it is need to create the links with 'All' application group for new sources
INSERT APM.APPLICATIONSOURCEMACHINE
( APPLICATIONID ,
SOURCEID ,
MACHINEID
)
SELECT
@ALLAPPID
,s.sourceid
,m.machineId
FROM
APM.MACHINE (NOLOCK) AS m
CROSS JOIN @NEWSOURCES as s
WHERE
NOT EXISTS
(
SELECT * FROM APM.APPLICATIONSOURCEMACHINE (NOLOCK) AS a
WHERE a.SOURCEID = s.sourceid AND a.APPLICATIONID = @ALLAPPID AND m.MACHINEid = a.machineid
)
END

/*------------------sync eventgroup------------------*/

/* updating server or client event group */
IF EXISTS(SELECT * FROM @EVENTGROUP WHERE client = 0)
BEGIN
/* updating server event group records by hashavalue*/
UPDATE G
SET eventclasstype = sync.eventclasstype
,rootnodename = sync.rootnodename
,aspect = sync.aspect
,firsteventdate = CASE WHEN sync.firsteventdate &lt; g.firsteventdate THEN sync.firsteventdate ELSE g.firsteventdate END
,lasteventdate = CASE WHEN sync.lasteventdate &gt; g.lasteventdate THEN sync.lasteventdate ELSE g.lasteventdate END
,description = sync.description
,sourceid = s.SourceId
FROM APM.eventGroup g
JOIN @EVENTGROUP sync ON sync.hashvalue = g.hashvalue AND sync.client = 0
JOIN APM.Source AS s ON s.source = sync.source
/*Permit number of affected records*/
SET @UPDATED_ROWCOUNT = @@ROWCOUNT

/* Insert new server event group which are not found by hashvalue */
INSERT APM.eventgroup (
firsteventdate
,lasteventdate
,eventclasstype
,rootnodename
,aspect
,hashvalue
,description
,sourceid
)
SELECT DISTINCT
sync.firsteventdate
,sync.lasteventdate
,sync.eventclasstype
,sync.rootnodename
,sync.aspect
,sync.hashvalue
,sync.description
,s.SourceId
FROM @EVENTGROUP sync
JOIN APM.Source AS s ON s.source = sync.source
WHERE
sync.client = 0 AND NOT EXISTS (SELECT * FROM APM.eventgroup WHERE (hashvalue = sync.hashvalue))
SET @INSERTED_ROWCOUNT = @@ROWCOUNT

/* Log about inserted records for verbal log mode*/
IF @TRACELEVEL = 4
BEGIN
SELECT @MESSAGE = MESSAGE FROM APM.MESSAGES WHERE ID = 50024
RAISERROR (@MESSAGE, 0, 1, @INSERTED_ROWCOUNT, 'eventGroup') WITH NOWAIT;
END

/* Number of records from package */
SELECT @CHANGED_ROWCOUNT = COUNT(*) FROM @EVENTGROUP WHERE client = 0

/* Calculate not affected packages records which are not processing */
SET @ROWNOTAFFECTED = @CHANGED_ROWCOUNT - (@INSERTED_ROWCOUNT + @UPDATED_ROWCOUNT)

/* It is need clear flags because client group records can be find in the package */
SELECT @INSERTED_ROWCOUNT = 0, @UPDATED_ROWCOUNT = 0
END
IF EXISTS(SELECT * FROM @EVENTGROUP WHERE client = 1)
BEGIN
/* updating client event group records by hashavalue*/
UPDATE G
SET
firsteventdate = CASE WHEN sync.firsteventdate &lt; g.firsteventdate THEN sync.firsteventdate ELSE g.firsteventdate END
,lasteventdate = CASE WHEN sync.lasteventdate &gt; g.lasteventdate THEN sync.lasteventdate ELSE g.lasteventdate END
FROM APM.CSEVENTGROUP g
JOIN @EVENTGROUP sync ON sync.hashvalue = g.hashvalue AND sync.client = 1

/*Permit number of affected records*/
SET @UPDATED_ROWCOUNT = @@ROWCOUNT

/* Insert new server event group which are not found by hashvalue */
INSERT APM.CSEVENTGROUP (
firsteventdate
,lasteventdate
,hashvalue
,description
,sourceid
)
SELECT DISTINCT
sync.firsteventdate
,sync.lasteventdate
,sync.hashvalue
,sync.description
,s.SourceId
FROM
@EVENTGROUP sync
JOIN APM.Source AS s ON s.source = sync.source
WHERE
sync.client = 1 AND NOT EXISTS (SELECT * FROM APM.CSEVENTGROUP WHERE (hashvalue = sync.hashvalue))
SET @INSERTED_ROWCOUNT = @@ROWCOUNT

/* Log about inserted records for verbal log mode */
IF @TRACELEVEL = 4
BEGIN
SELECT @MESSAGE = MESSAGE FROM APM.MESSAGES WHERE ID = 50024
RAISERROR (@MESSAGE, 0, 1, @INSERTED_ROWCOUNT, 'CSEVENTGROUP') WITH NOWAIT;
END

/* Number of records from package */
SELECT @CHANGED_ROWCOUNT = COUNT(*) FROM @EVENTGROUP WHERE client = 1

/* Calculate not affected packages records which are not processing */
/* It is also need to add not affected records from previos processing (server event group)*/
SET @ROWNOTAFFECTED = @ROWNOTAFFECTED + @CHANGED_ROWCOUNT - (@INSERTED_ROWCOUNT + @UPDATED_ROWCOUNT)
END
END TRY
BEGIN CATCH
IF (@@TRANCOUNT &gt; 0)
ROLLBACK TRAN

SELECT
@ERRORNUMBER = ERROR_NUMBER()
,@ERRORSEVERITY = ERROR_SEVERITY()
,@ERRORSTATE = ERROR_STATE()
,@ERRORLINE = ERROR_LINE()
,@ERRORPROCEDURE = ISNULL(ERROR_PROCEDURE(), '-')
,@ERRORMESSAGETEXT = ERROR_MESSAGE()

SET @ERRORIND = 1
END CATCH

IF @XMLDOCHANDLE IS NOT NULL
EXEC sp_xml_removedocument @XMLDOCHANDLE

-- report error if any
IF (@ERRORIND = 1)
BEGIN
DECLARE @ADJUSTEDERRORSEVERITY int

SET @ADJUSTEDERRORSEVERITY = CASE
WHEN @ERRORSEVERITY = 2601 OR @ERRORSEVERITY = 2627 THEN 0
WHEN @ERRORSEVERITY &gt; 18 THEN 18
ELSE @ERRORSEVERITY
END

SELECT @ERROR_MESSAGE = message FROM APM.Messages WHERE id = 50004
RAISERROR (@ERROR_MESSAGE, @ADJUSTEDERRORSEVERITY, 1
,@ERRORNUMBER
,@ERRORSEVERITY
,@ERRORSTATE
,@ERRORPROCEDURE
,@ERRORLINE
,@ERRORMESSAGETEXT
)
END
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.PCProcess_sync'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.PCProcess_sync AS RETURN 1')
END
GO
/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: PCProcess_sync */
/* USED IN: Synchronization PCProcess table. Call by Intercept Reporting Services */
/* INPUT PARAMETERS: */
/* @OBJECTKEYXML - xml package syncronization data */
/* @TRACELEVEL - trace level. Reserved. */
/* OUTPUT PARAMETERS: */
/* @ROWNOTAFFECTED - number of records from package which haven't been */
/* synchronized.Reserved. */
/* Note: */
/* If there are records which have not been transferred that they have been already */
/* transferred from other SEVIEWER database earlier. Any other reason will cause a */
/* exception at an insert */
/************************************************************************************/
ALTER PROCEDURE APM.PCProcess_sync
@OBJECTKEYXML ntext,
@TRACELEVEL int,
@ROWNOTAFFECTED int output
AS
BEGIN
SET NOCOUNT ON

DECLARE
@ERRORIND bit
,@ERRORMESSAGE nvarchar(max)
,@ERRORNUMBER int
,@ERRORSEVERITY int
,@ERRORSTATE int
,@ERRORLINE int
,@ERRORPROCEDURE nvarchar(256)
,@ERRORMESSAGETEXT nvarchar(max)

SET @ERRORIND = 0

BEGIN TRY

SET @ROWNOTAFFECTED = 0

DECLARE
@EXECRESULT int
,@XMLDOCHANDLE int
,@ERROR_MESSAGE nvarchar(max)

EXEC @EXECRESULT = sp_xml_preparedocument @XMLDOCHANDLE OUTPUT, @OBJECTKEYXML
IF @EXECRESULT &lt;&gt; 0
BEGIN
SELECT @ERROR_MESSAGE = message FROM APM.messages WHERE id = 50002
RAISERROR(@ERROR_MESSAGE, 16, 1, 'PCProcess_sync', @EXECRESULT)
END

DECLARE @PCPROCESS TABLE (
id int IDENTITY(1,1)
,process nvarchar(255) collate database_default
,extratype int
,extrainfo nvarchar(255) collate database_default
,hashvalue nvarchar(50) collate database_default
)

----Fill table from package
INSERT @PCPROCESS (
process
,extratype
,extrainfo
,hashvalue
)
SELECT
process
,extratype
,extrainfo
,hashvalue
FROM OPENXML(@XMLDOCHANDLE, 'rows/row', 2) WITH (
process nvarchar(255)
,extratype int
,extrainfo nvarchar(255)
,hashvalue nvarchar(50) ) xml

EXEC sp_xml_removedocument @XMLDOCHANDLE

SET @XMLDOCHANDLE = NULL

--remove duplicates by hashvalue
Delete pr1
from @PCPROCESS pr1
join @PCPROCESS pr2 on pr1.id &gt; pr2.id and pr1.hashvalue = pr2.hashvalue

UPDATE pr
SET process = sync.process
,extratype = sync.extratype
,extrainfo = sync.extrainfo
FROM APM.PCProcess pr
JOIN @PCPROCESS sync ON sync.hashvalue = pr.hashvalue

INSERT APM.pcprocess (process, extratype, extrainfo, hashvalue)
SELECT DISTINCT sync.process, sync.extratype, sync.extrainfo, sync.hashvalue
FROM @PCPROCESS sync
WHERE NOT EXISTS (SELECT * FROM APM.PCProcess WHERE (hashvalue = sync.hashvalue))

END TRY
BEGIN CATCH
IF (@@TRANCOUNT &gt; 0)
ROLLBACK TRAN

SELECT
@ERRORNUMBER = ERROR_NUMBER()
,@ERRORSEVERITY = ERROR_SEVERITY()
,@ERRORSTATE = ERROR_STATE()
,@ERRORLINE = ERROR_LINE()
,@ERRORPROCEDURE = ISNULL(ERROR_PROCEDURE(), '-')
,@ERRORMESSAGETEXT = ERROR_MESSAGE()

SET @ERRORIND = 1
END CATCH

IF @XMLDOCHANDLE IS NOT NULL
EXEC sp_xml_removedocument @XMLDOCHANDLE

-- report error if any
IF (@ERRORIND = 1)
BEGIN
DECLARE @ADJUSTEDERRORSEVERITY int

SET @ADJUSTEDERRORSEVERITY = CASE
WHEN @ERRORSEVERITY = 2601 OR @ERRORSEVERITY = 2627 THEN 0
WHEN @ERRORSEVERITY &gt; 18 THEN 18
ELSE @ERRORSEVERITY
END

SELECT @ERROR_MESSAGE = message FROM APM.Messages WHERE id = 50004
RAISERROR (@ERROR_MESSAGE, @ADJUSTEDERRORSEVERITY, 1
,@ERRORNUMBER
,@ERRORSEVERITY
,@ERRORSTATE
,@ERRORPROCEDURE
,@ERRORLINE
,@ERRORMESSAGETEXT
)
END
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.PCDescription_sync'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.PCDescription_sync AS RETURN 1')
END
GO
/*********************************************************************************** */
/* OBJECT: Stored Procedure */
/* NAME: PCDescription_sync */
/* USED IN: Synchronization PCDescription table. Call by Intercept Reporting Services */
/* INPUT PARAMETERS: */
/* @OBJECTKEYXML - xml package syncronization data */
/* @TRACELEVEL - trace level. Reserved. */
/* OUTPUT PARAMETERS: */
/* @ROWNOTAFFECTED - number of records from package which haven't been */
/* synchronized.Reserved. */
/* Note: */
/* If there are records which have not been transferred that they have been already */
/* transferred from other SEVIEWER database earlier. Any other reason will cause a */
/* exception at an insert */
/*************************************************************************************/
ALTER PROCEDURE APM.PCDescription_sync
@OBJECTKEYXML ntext,
@TRACELEVEL int,
@ROWNOTAFFECTED int output
AS
BEGIN
SET NOCOUNT ON

DECLARE
@ERRORIND bit
,@ERRORMESSAGE nvarchar(max)
,@ERRORNUMBER int
,@ERRORSEVERITY int
,@ERRORSTATE int
,@ERRORLINE int
,@ERRORPROCEDURE nvarchar(256)
,@ERRORMESSAGETEXT nvarchar(max)

SET @ERRORIND = 0

BEGIN TRY

DECLARE
@EXECRESULT int
,@XMLDOCHANDLE int
,@ERROR_MESSAGE nvarchar(max)

SET @ROWNOTAFFECTED = 0

EXEC @EXECRESULT = sp_xml_preparedocument @XMLDOCHANDLE OUTPUT, @OBJECTKEYXML
IF @EXECRESULT &lt;&gt; 0
BEGIN
SELECT @ERROR_MESSAGE = message FROM APM.messages WHERE id = 50002
RAISERROR(@ERROR_MESSAGE, 16, 1, 'PCDescription_sync', @EXECRESULT)
END

DECLARE @PCDESCRIPTION TABLE (
name nvarchar(255) collate database_default NOT NULL
,description nvarchar(max) collate database_default NULL
)

----Fill table from package
INSERT @PCDESCRIPTION (
name
,description
)
SELECT
Name
,Description
FROM OPENXML(@XMLDOCHANDLE, 'rows/row', 2) WITH (
name nvarchar(255)
,description nvarchar(max) ) xml

EXEC sp_xml_removedocument @XMLDOCHANDLE

SET @XMLDOCHANDLE = NULL

--------------sync description---------
UPDATE d
SET Name = sync.name, Description = sync.description
FROM APM.PCDescription d
JOIN @PCDESCRIPTION sync ON sync.name = d.Name

INSERT APM.pcdescription (name, description)
SELECT DISTINCT sync.name, sync.description
FROM @PCDESCRIPTION sync
WHERE NOT EXISTS (SELECT * FROM APM.PCDescription WHERE (name = sync.name))

END TRY
BEGIN CATCH
IF (@@TRANCOUNT &gt; 0)
ROLLBACK TRAN

SELECT
@ERRORNUMBER = ERROR_NUMBER()
,@ERRORSEVERITY = ERROR_SEVERITY()
,@ERRORSTATE = ERROR_STATE()
,@ERRORLINE = ERROR_LINE()
,@ERRORPROCEDURE = ISNULL(ERROR_PROCEDURE(), '-')
,@ERRORMESSAGETEXT = ERROR_MESSAGE()

SET @ERRORIND = 1
END CATCH

IF @XMLDOCHANDLE IS NOT NULL
EXEC sp_xml_removedocument @XMLDOCHANDLE

-- report error if any
IF (@ERRORIND = 1)
BEGIN
DECLARE @ADJUSTEDERRORSEVERITY int

SET @ADJUSTEDERRORSEVERITY = CASE
WHEN @ERRORSEVERITY = 2601 OR @ERRORSEVERITY = 2627 THEN 0
WHEN @ERRORSEVERITY &gt; 18 THEN 18
ELSE @ERRORSEVERITY
END

SELECT @ERROR_MESSAGE = message FROM APM.Messages WHERE id = 50004
RAISERROR (@ERROR_MESSAGE, @ADJUSTEDERRORSEVERITY, 1
,@ERRORNUMBER
,@ERRORSEVERITY
,@ERRORSTATE
,@ERRORPROCEDURE
,@ERRORLINE
,@ERRORMESSAGETEXT
)
END
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.PMCREATEEVENTTRACES'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.PMCREATEEVENTTRACES AS RETURN 1')
END
GO
/**************************************************************************************************/
/* PROCEDURE PMCREATEEVENTTRACES */
/* Description: */
/* It create trace and event traces. */
/* Warning: It use temporary table #RESULT(EventId int). Therefore it is need to */
/* create #RESULT table before call procedure */
/* */
/* Input parameters: */
/* @DATA - XML OBJECT VIEW */
/* @CLIENT - 0: server events 1:client events */
/**************************************************************************************************/
ALTER PROCEDURE [APM].[PMCREATEEVENTTRACES]
@CLIENT bit
,@DATA nvarchar(MAX)
AS
SET NOCOUNT ON

DECLARE
@TRACEOUTPUT TABLE (NEWTRACE int, PMSTATUS nvarchar(max))

--create trace package
INSERT APM.PMTRACE (PMSTATUS)
OUTPUT INSERTED.PMTRACEID, INSERTED.PMSTATUS INTO @TRACEOUTPUT
SELECT DISTINCT r.PMSTATUS FROM #STATUSTABLE r

IF @@ROWCOUNT = 0
RAISERROR(N'#STATUSTABLE is empty. Imposible created trace.', 0, 1) WITH NOWAIT

-- update data
IF @DATA IS NOT NULL
UPDATE t
SET t.DATA = @DATA
FROM APM.PMTRACE t
JOIN @TRACEOUTPUT nt ON T.pmtraceId = nt.NEWTRACE

--server trace
IF @CLIENT = 0
--Fill server event trace
--Join with Event table is need because these events can be deleted by grooming
INSERT APM.PMSERVEREVENTTRACE(EVENTID, PMTRACEID)
SELECT e.EVENTID, t.NEWTRACE
FROM #STATUSTABLE AS st
JOIN APM.EVENT (NOLOCK) AS e ON e.EVENTID = st.EVENTID
JOIN @TRACEOUTPUT t ON t.PMSTATUS = st.PMSTATUS

IF @CLIENT = 1
--Fill client event trace
--Join with Event table is need because these events can be deleted by grooming
INSERT APM.PMCLIENTEVENTTRACE(CSEVENTID, PMTRACEID)
SELECT e.CSEVENTID, t.NEWTRACE
FROM #STATUSTABLE AS st
JOIN APM.CSEVENT (NOLOCK) AS e ON e.CSEVENTID = st.EVENTID
JOIN @TRACEOUTPUT t ON t.PMSTATUS = st.PMSTATUS
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.ServerEvent_sync'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.ServerEvent_sync AS RETURN 1')
END
GO
/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: ServerEvent_sync */
/* USED IN: Synchronization server event. */
/* Call by Intercept Reporting Services */
/* INPUT PARAMETERS: */
/* @OBJECTKEYXML - xml package syncronization data */
/* @TRACELEVEL - trace level. Reserved. */
/* OUTPUT PARAMETERS: */
/* @ROWNOTAFFECTED - number of records from package which haven't been */
/* synchronized. */
/************************************************************************************/
ALTER PROCEDURE [APM].[ServerEvent_sync]
@OBJECTKEYXML ntext
,@DATABASEID int
,@TRACELEVEL int
,@ROWNOTAFFECTED int output
AS
BEGIN
SET NOCOUNT ON

DECLARE
@ERRORIND bit
,@ERRORMESSAGE nvarchar(max)
,@ERRORNUMBER int
,@ERRORSEVERITY int
,@ERRORSTATE int
,@ERRORLINE int
,@ERRORPROCEDURE nvarchar(256)
,@ERRORMESSAGETEXT nvarchar(max)

SET @ERRORIND = 0

BEGIN TRY

SET @ROWNOTAFFECTED = 0

DECLARE
@EXECRESULT int
,@XMLDOCHANDLE int
,@INSERTED_ROWCOUNT int
,@CHANGED_ROWCOUNT int
,@ERROR_MESSAGE nvarchar(max)

--allocate memory for xml package
EXEC @EXECRESULT = sp_xml_preparedocument @XMLDOCHANDLE OUTPUT, @OBJECTKEYXML
IF @EXECRESULT &lt;&gt; 0
BEGIN
SELECT @ERROR_MESSAGE = message FROM APM.messages WHERE id = 50002
RAISERROR(@ERROR_MESSAGE, 16, 1, 'ServerEvent_sync', @EXECRESULT)
END

-----temporary table variable for the keeping xml package
DECLARE @EVENT TABLE (
grouphash nvarchar(50) collate database_default
,rootnodename nvarchar(255) collate database_default
,rootfunction nvarchar(255) collate database_default
,component nvarchar(255) collate database_default
,source nvarchar(255) collate database_default
,eventduration decimal(35,0)
,machinename nvarchar(255) collate database_default
,utceventdate datetime
,eventclasstype nvarchar(50) collate database_default
,aspect nvarchar(50) collate database_default
,username nvarchar(255) collate database_default
,exceptionclass nvarchar(255) collate database_default
,description nvarchar(255) collate database_default
,category nvarchar(255) collate database_default
,rowguid nvarchar(15) collate database_default
,seviewerdbid int
,sevieweregid int
,heavylight int
,pmstatus tinyint
)

---- parse and insert xml package to the temporary table variabale
INSERT @EVENT (
grouphash
,rootnodename
,rootfunction
,component
,source
,eventduration
,machinename
,utceventdate
,eventclasstype
,aspect
,username
,exceptionclass
,description
,category
,rowguid
,sevieweregid
,heavylight
,pmstatus
)
SELECT
grouphash
,rootnodename
,rootfunction
,component
,source
,eventduration
,machinename
,utceventdate
,eventclasstype
,aspect
,username
,exceptionclass
,description
,category
,rowguid
,sevieweregid
,heavylight
,pmstatus
FROM OPENXML(@XMLDOCHANDLE, 'rows/row', 2) WITH (
grouphash nvarchar(50)
,rootnodename nvarchar(255)
,rootfunction nvarchar(255)
,component nvarchar(255)
,source nvarchar(255)
,eventduration decimal(35,0)
,machinename nvarchar(255)
,utceventdate datetime
,eventclasstype nvarchar(50)
,aspect nvarchar(50)
,username nvarchar(255)
,exceptionclass nvarchar(255)
,description nvarchar(255)
,category nvarchar(255)
,rowguid nvarchar(15)
,sevieweregid int -------- reference to the seviewer event group ---
,heavylight int
,pmstatus tinyint
) xml

--free memory of xml package
EXEC sp_xml_removedocument @XMLDOCHANDLE

SET @XMLDOCHANDLE = NULL

----------sync event------------

-------- update reference to the seviewer database -------
UPDATE @EVENT SET seviewerdbid = @DATABASEID

-------- sync Users table---------------
INSERT Users (name)
SELECT DISTINCT sync.username FROM @EVENT sync
WHERE NOT EXISTS(SELECT u.name FROM APM.Users u WHERE sync.username = u.name)
AND sync.username IS NOT NULL AND sync.username &lt;&gt; ''

DECLARE @ALLAPPID int
DECLARE @NEWMACHINES TABLE (machineId int)

----- machine can be removed using "Remove computers wizard" so it is need synchronize machines ----
INSERT APM.MACHINE (MACHINE) OUTPUT INSERTED.MACHINEID INTO @NEWMACHINES
SELECT DISTINCT machinename FROM @EVENT e
WHERE NOT EXISTS (SELECT * FROM APM.machine m (NOLOCK) WHERE m.machine = e.machinename)

IF EXISTS(SELECT * FROM @NEWMACHINES)
BEGIN
IF @ALLAPPID IS NULL
SELECT @ALLAPPID = APPLICATIONID FROM APM.APPLICATION (NOLOCK) WHERE APPLICATION = N'All'
---- it is need to create the links with 'All' application group for new sources
INSERT APM.APPLICATIONSOURCEMACHINE
( APPLICATIONID ,
SOURCEID ,
MACHINEID
)
SELECT
@ALLAPPID
,s.SourceId
,m.machineId
FROM
APM.SOURCE (NOLOCK) AS s
CROSS JOIN @NEWMACHINES as m
WHERE
NOT EXISTS
(
SELECT * FROM APM.APPLICATIONSOURCEMACHINE (NOLOCK) AS a
WHERE a.SOURCEID = s.sourceId AND a.APPLICATIONID = @ALLAPPID AND m.machineId = a.machineid
)
END

----- sources can be removed using "Remove applications wizard" so it is need synchronize sources ----
DECLARE @NEWSOURCES TABLE (sourceid int)

INSERT APM.SOURCE (SOURCE) OUTPUT INSERTED.SOURCEID INTO @NEWSOURCES
SELECT DISTINCT source FROM @EVENT e
WHERE NOT EXISTS (SELECT * FROM APM.source s (NOLOCK) WHERE s.source = e.source)

IF EXISTS(SELECT * FROM @NEWSOURCES)
BEGIN
IF @ALLAPPID IS NULL
SELECT @ALLAPPID = APPLICATIONID FROM APM.APPLICATION (NOLOCK) WHERE APPLICATION = N'All'
---- it is need to create the links with 'All' application group for new machines
INSERT APM.APPLICATIONSOURCEMACHINE
( APPLICATIONID ,
SOURCEID ,
MACHINEID
)
SELECT
@ALLAPPID
,s.sourceid
,m.machineId
FROM
APM.MACHINE (NOLOCK) AS m
CROSS JOIN @NEWSOURCES as s
WHERE
NOT EXISTS
(
SELECT * FROM APM.APPLICATIONSOURCEMACHINE (NOLOCK) AS a
WHERE a.SOURCEID = s.sourceid AND a.APPLICATIONID = @ALLAPPID AND m.MACHINEid = a.machineid
)
END


-------------- sync event table ------------------

-- temporary table for traces. It will contains event id of the new events.
CREATE TABLE #STATUSTABLE(EVENTID int, PMSTATUS tinyint)

INSERT EVENT (
eventgroupid
,sourceid
,eventduration
,machineid
,utceventdate
,eventclasstype
,rootnodename
,aspect
,exceptionclass
,description
,category
,rowguid
,seviewerdbid
,sevieweregid
,heavylight
,pmstatus
)
OUTPUT INSERTED.EVENTID, INSERTED.PMSTATUS
INTO #STATUSTABLE
SELECT
g.eventgroupid
,s.sourceid
,sync.eventduration
,m.MACHINEID
,sync.utceventdate
,sync.eventclasstype
,sync.rootnodename
,sync.aspect
,sync.exceptionclass
,sync.description
,sync.category
,sync.rowguid
,sync.seviewerdbid
,sync.sevieweregid
,sync.heavylight
,pmstatus
FROM
@EVENT sync
JOIN APM.source s (NOLOCK) ON s.source = sync.source
JOIN APM.EventGroup g (NOLOCK) ON g.hashvalue = sync.grouphash
JOIN APM.MACHINE m (NOLOCK) ON m.machine = sync.machinename
WHERE NOT EXISTS(SELECT * FROM event e (NOLOCK) WHERE sync.rowguid = e.rowguid)
--should be the same order between RowGuid and primary key of the Event table
ORDER BY CAST(SUBSTRING(sync.rowguid, CHARINDEX('-', rowguid) + 1, LEN(rowguid)) AS INT)

SET @INSERTED_ROWCOUNT = @@ROWCOUNT

--Create event traces for server events
EXEC APM.PMCREATEEVENTTRACES 0, NULL

-----------sync event with username------------------
UPDATE e SET
e.userid = u.userid
FROM
APM.event e
JOIN @EVENT sync ON sync.rowguid = e.rowguid
JOIN Users u (NOLOCK) ON sync.username = u.Name

INSERT EVENTDETAIL
(
EventId
,Name
,[Value]
,[ValueType]
)
SELECT
e.EventId
,'COMPONENT'
,sync.component
,'PM'
FROM
@EVENT AS sync
JOIN APM.Event AS e (NOLOCK) ON sync.rowguid = e.rowguid

INSERT EVENTDETAIL
(
EventId
,Name
,[Value]
,[ValueType]
)
SELECT
e.EventId
,'ROOTFUNCTION'
,sync.rootfunction
,'PM'
FROM
@EVENT AS sync
JOIN APM.Event AS e (NOLOCK) ON sync.rowguid = e.rowguid

SELECT @CHANGED_ROWCOUNT = COUNT(*) FROM @EVENT
SET @ROWNOTAFFECTED = @CHANGED_ROWCOUNT - @INSERTED_ROWCOUNT

END TRY
BEGIN CATCH
IF (@@TRANCOUNT &gt; 0)
ROLLBACK TRAN

SELECT
@ERRORNUMBER = ERROR_NUMBER()
,@ERRORSEVERITY = ERROR_SEVERITY()
,@ERRORSTATE = ERROR_STATE()
,@ERRORLINE = ERROR_LINE()
,@ERRORPROCEDURE = ISNULL(ERROR_PROCEDURE(), '-')
,@ERRORMESSAGETEXT = ERROR_MESSAGE()

SET @ERRORIND = 1
END CATCH

IF @XMLDOCHANDLE IS NOT NULL
EXEC sp_xml_removedocument @XMLDOCHANDLE

-- report error if any
IF (@ERRORIND = 1)
BEGIN
DECLARE @ADJUSTEDERRORSEVERITY int

SET @ADJUSTEDERRORSEVERITY = CASE
WHEN @ERRORSEVERITY = 2601 OR @ERRORSEVERITY = 2627 THEN 0
WHEN @ERRORSEVERITY &gt; 18 THEN 18
ELSE @ERRORSEVERITY
END

SELECT @ERROR_MESSAGE = message FROM APM.Messages WHERE id = 50004
RAISERROR (@ERROR_MESSAGE, @ADJUSTEDERRORSEVERITY, 1
,@ERRORNUMBER
,@ERRORSEVERITY
,@ERRORSTATE
,@ERRORPROCEDURE
,@ERRORLINE
,@ERRORMESSAGETEXT
)
END
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.PerformanceNode_sync'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.PerformanceNode_sync AS RETURN 1')
END
GO
ALTER PROCEDURE [APM].[PerformanceNode_sync]
@OBJECTKEYXML ntext,
@TRACELEVEL int,
@ROWNOTAFFECTED int output
AS
BEGIN
SET NOCOUNT ON

DECLARE
@ERRORIND bit
,@ERRORMESSAGE nvarchar(max)
,@ERRORNUMBER int
,@ERRORSEVERITY int
,@ERRORSTATE int
,@ERRORLINE int
,@ERRORPROCEDURE nvarchar(256)
,@ERRORMESSAGETEXT nvarchar(max)

SET @ERRORIND = 0

BEGIN TRY

SET @ROWNOTAFFECTED = 0

DECLARE
@EXECRESULT int
,@XMLDOCHANDLE int
,@ERROR_MESSAGE nvarchar(max)
,@INSERTED_ROWCOUNT int
,@CHANGED_ROWCOUNT int
,@MESSAGE nvarchar(max)

EXEC @EXECRESULT = sp_xml_preparedocument @XMLDOCHANDLE OUTPUT, @OBJECTKEYXML
IF @EXECRESULT &lt;&gt; 0
BEGIN
SELECT @ERROR_MESSAGE = message FROM APM.messages WHERE id = 50002
RAISERROR(@ERROR_MESSAGE, 16, 1, 'PerformanceNode_sync', @EXECRESULT)
END


DECLARE @PERFORMANCENODE TABLE (
eventrowguid nvarchar(15) collate database_default
,description nvarchar(255) collate database_default
,functionname nvarchar(255) collate database_default
,duration decimal(35,0)
,hashcode nvarchar(255) collate database_default
,entryid int
,rowguid nvarchar(15) collate database_default
,client int
,isheaviestnode bit
)


INSERT @PERFORMANCENODE (
eventrowguid
,description
,functionname
,duration
,hashcode
,entryid
,rowguid
,client
,isheaviestnode
)
SELECT
xml.eventrowguid
,xml.description
,xml.functionname
,xml.duration
,xml.hashcode
,xml.entryid
,xml.rowguid
,xml.client
,xml.isheaviestnode
FROM
OPENXML(@XMLDOCHANDLE, 'rows/row', 2) WITH (
eventrowguid nvarchar(15)
,description nvarchar(255)
,functionname nvarchar(255)
,duration decimal(35,0)
,hashcode nvarchar(255)
,entryid int
,rowguid nvarchar(15)
,client int
,isheaviestnode bit
) xml


EXEC sp_xml_removedocument @XMLDOCHANDLE

SET @XMLDOCHANDLE = NULL

----------sync performanceNode------------

/* updating server or client performance */

IF EXISTS(SELECT * FROM @PERFORMANCENODE WHERE client = 0)
BEGIN
/* server performance */

INSERT APM.PerformanceNode (
eventid
,description
,functionname
,duration
,hashcode
,entryid
,rowguid
,isheaviestnode
)
SELECT
e.eventid
,sync.description
,sync.functionname
,sync.duration
,sync.hashcode
,sync.entryid
,sync.rowguid
,sync.isheaviestnode
FROM
@PERFORMANCENODE sync
JOIN APM.Event e (NOLOCK) ON e.rowguid = sync.eventrowguid
WHERE
sync.client = 0 AND NOT EXISTS(SELECT * FROM APM.performanceNode (NOLOCK) WHERE rowguid = sync.rowguid)
SET @INSERTED_ROWCOUNT = @@ROWCOUNT

IF @TRACELEVEL = 4
BEGIN
SELECT @MESSAGE = MESSAGE FROM APM.MESSAGES WHERE ID = 50024
RAISERROR (@MESSAGE, 0, 1, @INSERTED_ROWCOUNT, 'PerformanceNode') WITH NOWAIT;
END

SELECT @CHANGED_ROWCOUNT = COUNT(*) FROM @PERFORMANCENODE WHERE client = 0

SET @ROWNOTAFFECTED = @CHANGED_ROWCOUNT - @INSERTED_ROWCOUNT
SELECT @INSERTED_ROWCOUNT = 0
END
IF EXISTS(SELECT * FROM @PERFORMANCENODE WHERE client = 1)
BEGIN
/* client performance */

INSERT APM.csheaviestresource (
cseventid
,name
,duration
,rowguid
,isheaviestnode
)
SELECT
e.cseventid
,sync.description
,sync.duration
,sync.rowguid
,sync.isheaviestnode

FROM
@PERFORMANCENODE sync
JOIN APM.CSEvent e (NOLOCK) ON e.rowguid = sync.eventrowguid
WHERE
sync.client = 1 AND NOT EXISTS(SELECT * FROM APM.csheaviestresource (NOLOCK) WHERE rowguid = sync.rowguid)
SET @INSERTED_ROWCOUNT = @@ROWCOUNT

IF @TRACELEVEL = 4
BEGIN
SELECT @MESSAGE = MESSAGE FROM APM.MESSAGES WHERE ID = 50024
RAISERROR (@MESSAGE, 0, 1, @INSERTED_ROWCOUNT, 'csheaviestresource') WITH NOWAIT;
END

SELECT @CHANGED_ROWCOUNT = COUNT(*) FROM @PERFORMANCENODE WHERE client = 1

SET @ROWNOTAFFECTED = @ROWNOTAFFECTED + @CHANGED_ROWCOUNT - @INSERTED_ROWCOUNT
END
END TRY
BEGIN CATCH
IF (@@TRANCOUNT &gt; 0)
ROLLBACK TRAN

SELECT
@ERRORNUMBER = ERROR_NUMBER()
,@ERRORSEVERITY = ERROR_SEVERITY()
,@ERRORSTATE = ERROR_STATE()
,@ERRORLINE = ERROR_LINE()
,@ERRORPROCEDURE = ISNULL(ERROR_PROCEDURE(), '-')
,@ERRORMESSAGETEXT = ERROR_MESSAGE()

SET @ERRORIND = 1
END CATCH

IF @XMLDOCHANDLE IS NOT NULL
EXEC sp_xml_removedocument @XMLDOCHANDLE

-- report error if any
IF (@ERRORIND = 1)
BEGIN
DECLARE @ADJUSTEDERRORSEVERITY int

SET @ADJUSTEDERRORSEVERITY = CASE
WHEN @ERRORSEVERITY = 2601 OR @ERRORSEVERITY = 2627 THEN 0
WHEN @ERRORSEVERITY &gt; 18 THEN 18
ELSE @ERRORSEVERITY
END

SELECT @ERROR_MESSAGE = message FROM APM.Messages WHERE id = 50004
RAISERROR (@ERROR_MESSAGE, @ADJUSTEDERRORSEVERITY, 1
,@ERRORNUMBER
,@ERRORSEVERITY
,@ERRORSTATE
,@ERRORPROCEDURE
,@ERRORLINE
,@ERRORMESSAGETEXT
)
END
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.ExceptionNode_sync'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.ExceptionNode_sync AS RETURN 1')
END
GO
ALTER PROCEDURE APM.ExceptionNode_sync
@OBJECTKEYXML ntext
,@TRACELEVEL int
,@ROWNOTAFFECTED int output
AS
BEGIN
SET NOCOUNT ON

DECLARE
@ERRORIND bit
,@ERRORMESSAGE nvarchar(max)
,@ERRORNUMBER int
,@ERRORSEVERITY int
,@ERRORSTATE int
,@ERRORLINE int
,@ERRORPROCEDURE nvarchar(256)
,@ERRORMESSAGETEXT nvarchar(max)

SET @ERRORIND = 0

BEGIN TRY

SET @ROWNOTAFFECTED = 0

DECLARE
@EXECRESULT int
,@XMLDOCHANDLE int
,@ERROR_MESSAGE nvarchar(max)
,@INSERTED_ROWCOUNT int
,@CHANGED_ROWCOUNT int
,@MESSAGE nvarchar(max)

EXEC @EXECRESULT = sp_xml_preparedocument @XMLDOCHANDLE OUTPUT, @OBJECTKEYXML
IF @EXECRESULT &lt;&gt; 0
BEGIN
SELECT @ERROR_MESSAGE = message FROM APM.messages WHERE id = 50002
RAISERROR(@ERROR_MESSAGE, 16, 1, 'exceptionnode_sync', @EXECRESULT)
END

DECLARE @EXCEPTIONNODE TABLE (
eventrowguid nvarchar(15) collate database_default
,eventAction nvarchar(255) collate database_default
,description nvarchar(255) collate database_default
,exceptionmessage nvarchar(255) collate database_default
,exceptionclass nvarchar(255) collate database_default
,functionname nvarchar(255) collate database_default
,modulename nvarchar(255) collate database_default
,linenumber bigint
,entryid int
,hashcode nvarchar(255) collate database_default
,rowguid nvarchar(15) collate database_default
,client int
)

SET @ROWNOTAFFECTED = 0

INSERT @EXCEPTIONNODE (
eventrowguid
,eventAction
,description
,exceptionmessage
,exceptionclass
,functionname
,modulename
,linenumber
,entryid
,hashcode
,rowguid
,client
)
SELECT
eventrowguid
,eventaction
,description
,exceptionmessage
,exceptionclass
,functionname
,modulename
,linenumber
,entryid
,hashcode
,rowguid
,client
FROM OPENXML(@XMLDOCHANDLE, 'rows/row', 2) WITH (
eventrowguid nvarchar(15)
,eventaction nvarchar(255)
,description nvarchar(255)
,exceptionmessage nvarchar(255)
,exceptionclass nvarchar(255)
,functionname nvarchar(255)
,modulename nvarchar(255)
,linenumber bigint
,entryid int
,hashcode nvarchar(255)
,rowguid nvarchar(15)
,client int
) xml

EXEC sp_xml_removedocument @XMLDOCHANDLE

SET @XMLDOCHANDLE = NULL

----------sync exceptionNode------------
IF EXISTS(SELECT * FROM @EXCEPTIONNODE WHERE client = 0)
BEGIN
/* server exception */

INSERT APM.ExceptionNode (
eventid
,exceptionmessage
,exceptionclass
,functionname
,modulename
,linenumber
,description
,hashcode
,entryid
,rowguid
)
SELECT
e.eventid
,sync.exceptionmessage
,sync.exceptionclass
,sync.functionname
,sync.modulename
,sync.linenumber
,sync.description
,sync.hashcode
,sync.entryid
,sync.rowguid
FROM
@EXCEPTIONNODE sync
JOIN APM.Event e ON e.rowguid = sync.eventrowguid
WHERE sync.client = 0 AND NOT EXISTS(SELECT * FROM APM.ExceptionNode WHERE rowguid = sync.rowguid)
SET @INSERTED_ROWCOUNT = @@ROWCOUNT

IF @TRACELEVEL = 4
BEGIN
SELECT @MESSAGE = MESSAGE FROM APM.MESSAGES WHERE ID = 50024
RAISERROR (@MESSAGE, 0, 1, @INSERTED_ROWCOUNT, 'ExceptionNode') WITH NOWAIT;
END

SELECT @CHANGED_ROWCOUNT = COUNT(*) FROM @EXCEPTIONNODE where client = 0

SET @ROWNOTAFFECTED = @CHANGED_ROWCOUNT - @INSERTED_ROWCOUNT
SET @INSERTED_ROWCOUNT = 0
END

IF EXISTS(SELECT * FROM @EXCEPTIONNODE WHERE client = 1)
BEGIN
/* client exception */
INSERT APM.CSEXEVENT (
cseventid
,action
,exmessage
,extype
,exfunction
,rowguid
)
SELECT
e.cseventid
,sync.eventAction
,sync.exceptionmessage
,sync.exceptionclass
,sync.functionname
,sync.rowguid
FROM
@EXCEPTIONNODE sync
JOIN APM.CSEvent e ON e.rowguid = sync.eventrowguid
WHERE sync.client = 1 AND NOT EXISTS(SELECT * FROM APM.ExceptionNode WHERE rowguid = sync.rowguid)
SET @INSERTED_ROWCOUNT = @@ROWCOUNT

IF @TRACELEVEL = 4
BEGIN
SELECT @MESSAGE = MESSAGE FROM APM.MESSAGES WHERE ID = 50024
RAISERROR (@MESSAGE, 0, 1, @INSERTED_ROWCOUNT, 'CSEXEVENT') WITH NOWAIT;
END

SELECT @CHANGED_ROWCOUNT = COUNT(*) FROM @EXCEPTIONNODE WHERE client = 1
SET @ROWNOTAFFECTED = @ROWNOTAFFECTED + @CHANGED_ROWCOUNT - @INSERTED_ROWCOUNT

END
END TRY
BEGIN CATCH
IF (@@TRANCOUNT &gt; 0)
ROLLBACK TRAN

SELECT
@ERRORNUMBER = ERROR_NUMBER()
,@ERRORSEVERITY = ERROR_SEVERITY()
,@ERRORSTATE = ERROR_STATE()
,@ERRORLINE = ERROR_LINE()
,@ERRORPROCEDURE = ISNULL(ERROR_PROCEDURE(), '-')
,@ERRORMESSAGETEXT = ERROR_MESSAGE()

SET @ERRORIND = 1
END CATCH

IF @XMLDOCHANDLE IS NOT NULL
EXEC sp_xml_removedocument @XMLDOCHANDLE

-- report error if any
IF (@ERRORIND = 1)
BEGIN
DECLARE @ADJUSTEDERRORSEVERITY int

SET @ADJUSTEDERRORSEVERITY = CASE
WHEN @ERRORSEVERITY = 2601 OR @ERRORSEVERITY = 2627 THEN 0
WHEN @ERRORSEVERITY &gt; 18 THEN 18
ELSE @ERRORSEVERITY
END

SELECT @ERROR_MESSAGE = message FROM APM.Messages WHERE id = 50004
RAISERROR (@ERROR_MESSAGE, @ADJUSTEDERRORSEVERITY, 1
,@ERRORNUMBER
,@ERRORSEVERITY
,@ERRORSTATE
,@ERRORPROCEDURE
,@ERRORLINE
,@ERRORMESSAGETEXT
)
END
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.PerfHourly_sync'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.PerfHourly_sync AS RETURN 1')
END
GO
ALTER PROCEDURE [APM].[PerfHourly_sync]
@OBJECTKEYXML ntext,
@DATABASEID int,
@TRACELEVEL int,
@ROWNOTAFFECTED int output
AS
BEGIN
SET NOCOUNT ON

DECLARE
@ERRORIND bit
,@ERRORMESSAGE nvarchar(max)
,@ERRORNUMBER int
,@ERRORSEVERITY int
,@ERRORSTATE int
,@ERRORLINE int
,@ERRORPROCEDURE nvarchar(256)
,@ERRORMESSAGETEXT nvarchar(max)

SET @ERRORIND = 0

BEGIN TRY

SET @ROWNOTAFFECTED = 0

DECLARE
@EXECRESULT int
,@XMLDOCHANDLE int
,@ERROR_MESSAGE nvarchar(max)
,@INSERTED_ROWCOUNT int
,@UPDATED_ROWCOUNT int
,@CHANGED_ROWCOUNT int
,@CURSOR_OPENED bit

SELECT @CHANGED_ROWCOUNT = 0, @UPDATED_ROWCOUNT = 0, @INSERTED_ROWCOUNT = 0, @CHANGED_ROWCOUNT = 0

EXEC @EXECRESULT = sp_xml_preparedocument @XMLDOCHANDLE OUTPUT, @OBJECTKEYXML
IF @EXECRESULT &lt;&gt; 0
BEGIN
SELECT @ERROR_MESSAGE = message FROM APM.messages WHERE id = 50002
RAISERROR(@ERROR_MESSAGE, 16, 1, 'PerfHourly_sync', @EXECRESULT)
END

DECLARE @PERFHOURLY TABLE (
type nvarchar(255) collate database_default
,machinename nvarchar(255) collate database_default
,source nvarchar(255) collate database_default
,pcprocessHash nvarchar(50) collate database_default
,is_state int
,utcdate datetime
,averagevalue float
,minvalue float
,maxvalue float
,samplecount float
,sumvalue float
,packagecounter int
,hashvalue nvarchar(50) collate database_default
,inserted bit
)

INSERT @PERFHOURLY (
type
,machinename
,source
,pcprocessHash
,is_state
,utcdate
,averagevalue
,minvalue
,maxvalue
,samplecount
,sumvalue
,packagecounter
,hashvalue
)
SELECT
type
,machinename
,source
,pcprocessHash
,is_state
,utcdate
,averagevalue
,minvalue
,maxvalue
,samplecount
,sumvalue
,packagecounter
,hashvalue
FROM OPENXML(@XMLDOCHANDLE, 'rows/row', 2) WITH (
type nvarchar(255)
,machinename nvarchar(255)
,source nvarchar(255)
,pcprocesshash nvarchar(50)
,is_state int
,utcdate datetime
,averagevalue float
,minvalue float
,maxvalue float
,samplecount float
,sumvalue float
,packagecounter int
,hashvalue nvarchar(50)
) xml

SET @CHANGED_ROWCOUNT = @@ROWCOUNT

EXEC sp_xml_removedocument @XMLDOCHANDLE

SET @XMLDOCHANDLE = NULL

DECLARE @ALLAPPID int
DECLARE @NEWMACHINES TABLE (machineId int)

------- machine can be removed using "Remove computers wizard" so it is need synchronize machines ----
INSERT APM.MACHINE (MACHINE) OUTPUT INSERTED.MACHINEID INTO @NEWMACHINES
SELECT DISTINCT machinename FROM @PERFHOURLY p
WHERE NOT EXISTS (SELECT * FROM APM.machine m (NOLOCK) WHERE m.machine = p.machinename) AND p.machinename is NOT null

IF EXISTS(SELECT * FROM @NEWMACHINES)
BEGIN
IF @ALLAPPID IS NULL
SELECT @ALLAPPID = APPLICATIONID FROM APM.APPLICATION (NOLOCK) WHERE APPLICATION = N'All'
---- it is need to create the links with 'All' application group for new sources
INSERT APM.APPLICATIONSOURCEMACHINE
( APPLICATIONID ,
SOURCEID ,
MACHINEID
)
SELECT
@ALLAPPID
,s.SourceId
,m.machineId
FROM
APM.SOURCE (NOLOCK) AS s
CROSS JOIN @NEWMACHINES as m
WHERE
NOT EXISTS
(
SELECT * FROM APM.APPLICATIONSOURCEMACHINE (NOLOCK) AS a
WHERE a.SOURCEID = s.sourceId AND a.APPLICATIONID = @ALLAPPID AND m.machineId = a.machineid
)
END

----- sources can be removed using "Remove applications wizard" so it is need synchronize sources ----
DECLARE @NEWSOURCES TABLE (sourceid int)

----- sources can be removed using "Remove applications wizard" so it is need synchronize sources ----
INSERT APM.SOURCE (SOURCE) OUTPUT INSERTED.SOURCEID INTO @NEWSOURCES
SELECT DISTINCT source FROM @PERFHOURLY p
WHERE NOT EXISTS (SELECT * FROM APM.source s (NOLOCK) WHERE s.source = p.source) AND p.source is NOT null

IF EXISTS(SELECT * FROM @NEWSOURCES)
BEGIN
IF @ALLAPPID IS NULL
SELECT @ALLAPPID = APPLICATIONID FROM APM.APPLICATION (NOLOCK) WHERE APPLICATION = N'All'
---- it is need to create the links with 'All' application group for new machines
INSERT APM.APPLICATIONSOURCEMACHINE
( APPLICATIONID ,
SOURCEID ,
MACHINEID
)
SELECT
@ALLAPPID
,s.sourceid
,m.machineId
FROM
APM.MACHINE (NOLOCK) AS m
CROSS JOIN @NEWSOURCES as s
WHERE
NOT EXISTS
(
SELECT * FROM APM.APPLICATIONSOURCEMACHINE (NOLOCK) AS a
WHERE a.SOURCEID = s.sourceid AND a.APPLICATIONID = @ALLAPPID AND m.MACHINEid = a.machineid
)
END

UPDATE sync
SET sync.inserted = 1
FROM @PERFHOURLY sync
WHERE NOT EXISTS(SELECT * FROM APM.PerfHourly p WHERE p.hashvalue = sync.hashvalue)

IF EXISTS(SELECT * FROM @PERFHOURLY sync WHERE sync.inserted = 1)
BEGIN
INSERT perfHourly(
pctypeid
,machineid
,sourceid
,pcprocessId
,is_state
,utcdate
,averagevalue
,minvalue
,maxvalue
,samplecount
,sumvalue
,packagecounter
,hashvalue
)
SELECT
t.pctypeid
,m.machineid
,s.sourceId
,pr.pcprocessId
,sync.is_state
,sync.utcdate
,sync.averagevalue
,sync.minvalue
,sync.maxvalue
,sync.samplecount
,sync.sumvalue
,sync.packagecounter
,sync.hashvalue
FROM
@PERFHOURLY sync
JOIN APM.Machine m ON m.machine = sync.machinename
JOIN APM.PCType t ON t.type = sync.type
LEFT JOIN APM.Source s ON s.source = sync.source
LEFT JOIN APM.PCProcess Pr ON PR.hashvalue = sync.pcprocessHash
WHERE
sync.inserted = 1

SET @INSERTED_ROWCOUNT = @@ROWCOUNT
END

IF EXISTS(SELECT * FROM @PERFHOURLY sync WHERE sync.inserted is null)
BEGIN
UPDATE p
SET
p.minvalue = CASE WHEN sync.minvalue &lt; p.minvalue THEN sync.minvalue ELSE p.minvalue END
,p.maxvalue = CASE WHEN sync.maxvalue &gt; p.maxvalue THEN sync.maxvalue ELSE p.maxvalue END
,p.samplecount = p.samplecount + sync.samplecount
,p.sumvalue = p.sumvalue + sync.sumvalue
,p.packagecounter = p.packagecounter + sync.packagecounter
,p.averagevalue = p.sumvalue / p.samplecount
FROM
APM.PerfHourly p
JOIN @PERFHOURLY sync ON sync.hashvalue = p.hashvalue
JOIN APM.Machine m ON m.machine = sync.machinename
JOIN APM.PCType t ON t.type = sync.type
LEFT JOIN APM.Source s ON s.source = sync.source
LEFT JOIN APM.PCProcess Pr ON PR.hashvalue = sync.pcprocessHash
WHERE sync.inserted IS NULL

SET @UPDATED_ROWCOUNT = @@ROWCOUNT
END

SET @ROWNOTAFFECTED = @CHANGED_ROWCOUNT - (@INSERTED_ROWCOUNT + @UPDATED_ROWCOUNT)

END TRY
BEGIN CATCH
IF (@@TRANCOUNT &gt; 0)
ROLLBACK TRAN

SELECT
@ERRORNUMBER = ERROR_NUMBER()
,@ERRORSEVERITY = ERROR_SEVERITY()
,@ERRORSTATE = ERROR_STATE()
,@ERRORLINE = ERROR_LINE()
,@ERRORPROCEDURE = ISNULL(ERROR_PROCEDURE(), '-')
,@ERRORMESSAGETEXT = ERROR_MESSAGE()

SET @ERRORIND = 1
END CATCH

IF @XMLDOCHANDLE IS NOT NULL
EXEC sp_xml_removedocument @XMLDOCHANDLE

-- report error if any
IF (@ERRORIND = 1)
BEGIN
DECLARE @ADJUSTEDERRORSEVERITY int

SET @ADJUSTEDERRORSEVERITY = CASE
WHEN @ERRORSEVERITY = 2601 OR @ERRORSEVERITY = 2627 THEN 0
WHEN @ERRORSEVERITY &gt; 18 THEN 18
ELSE @ERRORSEVERITY
END

SELECT @ERROR_MESSAGE = message FROM APM.Messages WHERE id = 50004
RAISERROR (@ERROR_MESSAGE, @ADJUSTEDERRORSEVERITY, 1
,@ERRORNUMBER
,@ERRORSEVERITY
,@ERRORSTATE
,@ERRORPROCEDURE
,@ERRORLINE
,@ERRORMESSAGETEXT
)
END
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.CheckDatabaseId'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.CheckDatabaseId AS RETURN 1')
END
GO
/* Procedure check database unique identificator and return error codes: */
/* 0 : Success. Database is synhronized with SEViewer database */
/* 1 : Error. Database is not synhronized with SEViewer database */
/* 2 : Error. Database is partialy synhronized with SEViewer database */
/* 3 : Error. Database is new */
ALTER PROCEDURE APM.CheckDatabaseId
@DBGUID uniqueidentifier
AS
BEGIN
DECLARE @ERROR int

SET @ERROR = 0

IF NOT EXISTS(SELECT * FROM APM.SEVIewerDB SV (NOLOCK) WHERE SV.DatabaseId = @DBGUID)
BEGIN
IF NOT EXISTS(SELECT * FROM APM.TASKS (NOLOCK))
BEGIN
SET @ERROR = 3
GOTO QUIT
END
IF EXISTS(SELECT * FROM APM.TASKS t (NOLOCK) WHERE t.SEVIewerDBId IS NULL)
BEGIN
SET @ERROR = 1
GOTO QUIT
END
END

IF EXISTS(SELECT * FROM APM.TASKS t (NOLOCK) WHERE t.SEVIewerDBId IS NULL)
BEGIN
SET @ERROR = 2
GOTO QUIT
END

QUIT:
RETURN @ERROR
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.CheckAndCreateDatabaseId'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.CheckAndCreateDatabaseId AS RETURN 1')
END
GO
/**************************************************************************************************/
/* Procedure check database unique identificator and find or create internal database identifier */
/* Procedure return error code: */
/* 0 : Success. Database is synhronized with SEViewer database */
/* 1 : Error. Database is not synhronized with SEViewer database */
/* 2 : Error. Database is partialy synhronized with SEViewer database */
/**************************************************************************************************/
/* Parameters: */
/* @DBGUID unique identificator */
/* @SEVIEWERURL unique identificator */
/* @DBGUID unique identificator */
ALTER PROCEDURE APM.CheckAndCreateDatabaseId
@DBGUID uniqueidentifier
,@SEVIEWERURL NVARCHAR(255)
,@TRACELEVEL INT
,@DBID int OUTPUT
AS
BEGIN
DECLARE @ERROR int

EXECUTE @ERROR = APM.CheckDatabaseId @DBGUID

SELECT @DBID = SEVIewerDBId FROM APM.SEVIewerDB SV (NOLOCK) WHERE SV.DatabaseId = @DBGUID
IF @@ROWCOUNT = 0
BEGIN
INSERT APM.SEVIEWERDB(DatabaseId, Address) Values(@DBGUID, @SEVIEWERURL)
SET @DBID = SCOPE_IDENTITY()
END

RETURN @ERROR
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.Config_sync'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.Config_sync AS RETURN 1')
END
GO
alter PROCEDURE APM.Config_sync
@OBJECTKEYXML ntext
,@TRACELEVEL INT
,@ROWNOTAFFECTED int output
AS
BEGIN
SET NOCOUNT ON

DECLARE
@ERRORIND bit
,@ERRORMESSAGE nvarchar(max)
,@ERRORNUMBER int
,@ERRORSEVERITY int
,@ERRORSTATE int
,@ERRORLINE int
,@ERRORPROCEDURE nvarchar(256)
,@ERRORMESSAGETEXT nvarchar(max)

SET @ERRORIND = 0

BEGIN TRY

DECLARE
@EXECRESULT int
,@XMLDOCHANDLE int
,@ERROR_MESSAGE nvarchar(max)
,@UPDATED_ROWCOUNT int
,@CHANGEDROWCOUNT int

SET @ROWNOTAFFECTED = 0

EXEC @EXECRESULT = sp_xml_preparedocument @XMLDOCHANDLE OUTPUT, @OBJECTKEYXML
IF @EXECRESULT &lt;&gt; 0
BEGIN
SELECT @ERROR_MESSAGE = message FROM APM.messages WHERE id = 50002
RAISERROR(@ERROR_MESSAGE, 16, 1, 'Config_sync', @EXECRESULT)
END

DECLARE @CONFIG TABLE (
configname nvarchar(50) NOT NULL
,configvalue nvarchar(max) NULL
,databaseid int
)

INSERT @CONFIG (
configname
,configvalue
,databaseid
)
SELECT
configname
,configvalue
,databaseid
FROM OPENXML(@XMLDOCHANDLE, 'rows/row', 2) WITH (
configname nvarchar(50)
,configvalue nvarchar(max)
,databaseid int) xml

EXEC sp_xml_removedocument @XMLDOCHANDLE

SET @XMLDOCHANDLE = NULL

UPDATE sv SET
Address = sync.configvalue
FROM
APM.SEViewerDb sv
JOIN @CONFIG sync ON sv.seviewerdbid = sync.databaseid AND sync.configname = 'SEVIEWERADDRESS'
SET @UPDATED_ROWCOUNT = @@ROWCOUNT

SELECT @CHANGEDROWCOUNT = COUNT(*) FROM @CONFIG WHERE configname = 'SEVIEWERADDRESS'

SET @ROWNOTAFFECTED = @CHANGEDROWCOUNT - @UPDATED_ROWCOUNT
END TRY
BEGIN CATCH
IF (@@TRANCOUNT &gt; 0)
ROLLBACK TRAN

SELECT
@ERRORNUMBER = ERROR_NUMBER()
,@ERRORSEVERITY = ERROR_SEVERITY()
,@ERRORSTATE = ERROR_STATE()
,@ERRORLINE = ERROR_LINE()
,@ERRORPROCEDURE = ISNULL(ERROR_PROCEDURE(), '-')
,@ERRORMESSAGETEXT = ERROR_MESSAGE()

SET @ERRORIND = 1
END CATCH

IF @XMLDOCHANDLE IS NOT NULL
EXEC sp_xml_removedocument @XMLDOCHANDLE

-- report error if any
IF (@ERRORIND = 1)
BEGIN
DECLARE @ADJUSTEDERRORSEVERITY int

SET @ADJUSTEDERRORSEVERITY = CASE
WHEN @ERRORSEVERITY = 2601 OR @ERRORSEVERITY = 2627 THEN 0
WHEN @ERRORSEVERITY &gt; 18 THEN 18
ELSE @ERRORSEVERITY
END
SELECT @ERROR_MESSAGE = message FROM APM.Messages WHERE id = 50004
RAISERROR (@ERROR_MESSAGE, @ADJUSTEDERRORSEVERITY, 1
,@ERRORNUMBER
,@ERRORSEVERITY
,@ERRORSTATE
,@ERRORPROCEDURE
,@ERRORLINE
,@ERRORMESSAGETEXT
)
END
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.PageEvent_sync'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.PageEvent_sync AS RETURN 1')
END
GO
/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: PageEvent_sync */
/* USED IN: Intercept reporting Service. Fill content information for the csm */
/* performance events. Internal stored procedure */
/* INPUT PARAMETERS: */
/* @XMLDOCHANDLE - memory handle (from sp_xml_preparedocument) */
/* @TRACELEVEL - trace flag (4 - diagnostic message will be generated */
/************************************************************************************/
ALTER PROCEDURE APM.PageEvent_sync
@XMLDOCHANDLE int
,@TRACELEVEL int
AS
BEGIN
SET NOCOUNT ON

DECLARE
@INSERTED_ROWCOUNT int
,@MESSAGE nvarchar(max)

DECLARE @PAGEEVENT TABLE (
event_rowguid nvarchar(15) collate database_default
,networktime decimal (35,0)
,servertime decimal (35,0)
,domtime decimal (35,0)
,peripheraltime decimal (35,0)
,onloadtime decimal (35,0)
,totaltime decimal (35,0)
,totalsize bigint
,latency bigint
,utcdate datetime
,SourceName nvarchar (255) collate database_default
)


INSERT @PAGEEVENT (
event_rowguid
,networktime
,servertime
,domtime
,peripheraltime
,onloadtime
,totaltime
,totalsize
,latency
,utcdate
,SourceName
)
SELECT
event_rowguid
,networktime
,servertime
,domtime
,peripheraltime
,onloadtime
,totaltime
,totalsize
,latency
,utcdate
,SourceName
FROM OPENXML(@XMLDOCHANDLE, 'rows/row/pageevent') WITH (
event_rowguid nvarchar(15) '../@rowguid'
,networktime decimal (35,0)
,servertime decimal (35,0)
,domtime decimal (35,0)
,peripheraltime decimal (35,0)
,onloadtime decimal (35,0)
,totaltime decimal (35,0)
,totalsize bigint
,latency bigint
,utcdate datetime '../@utceventdate'
,sourceName nvarchar (255) '../@source'
,client int '../@client'
) xml
WHERE xml.client = 2
-- Fill CSPageEvent table--------
INSERT APM.CSPageEvent (
cseventid
,networktime
,servertime
,domtime
,peripheraltime
,onloadtime
,totaltime
,totalsize
,latency
,utcdate
,sourceid
)
SELECT
e.cseventid
,sync.networktime
,sync.servertime
,sync.domtime
,sync.peripheraltime
,sync.onloadtime
,sync.totaltime
,sync.totalsize
,sync.latency
,sync.utcdate
,s.SourceId
FROM
@PAGEEVENT sync
JOIN APM.csevent e ON sync.event_rowguid = e.rowguid
JOIN APM.source s ON s.source = sync.SourceName

SET @INSERTED_ROWCOUNT = @@ROWCOUNT

IF @TRACELEVEL = 4
BEGIN
SELECT @MESSAGE = MESSAGE FROM APM.MESSAGES WHERE ID = 50024
RAISERROR (@MESSAGE, 0, 1, @INSERTED_ROWCOUNT, 'CSPageEvent') WITH NOWAIT;
END


-- Fill Periphial and Periphial Detail table--------
DECLARE @PERIPHIAL TABLE (
event_rowguid nvarchar(15) collate database_default
,type nvarchar (50) collate database_default
,totalsize bigint
,totaltime decimal (35,0)
,htmlSize bigint
)

INSERT INTO @PERIPHIAL
(
event_rowguid
,type
,totalsize
,totaltime
,htmlSize
)
SELECT
event_rowguid
,type
,totalsize
,totaltime
,htmlSize


FROM OPENXML(@XMLDOCHANDLE, 'rows/row/peripheral/row', 2) WITH (
event_rowguid nvarchar(15) '../../@rowguid'
,type nvarchar (50) '@type'
,totalsize bigint '@totalsize'
,totaltime decimal (35,0) '@totaltime'
,htmlSize bigint '../@htmlsize'
,client int '../../@client'
) xml
WHERE xml.client = 2

DECLARE @PERIPHIALDETAIL TABLE (
event_rowguid nvarchar(15) collate database_default
,type nvarchar (50) collate database_default
,domain nvarchar (255) collate database_default
,path nvarchar (255) collate database_default
,size bigint
,detail_totaltime decimal (35,0)
)


INSERT INTO @PERIPHIALDETAIL
(
event_rowguid
,type
,domain
,path
,size
,detail_totaltime
)
SELECT
event_rowguid
,type
,domain
,path
,size
,detail_totaltime
FROM OPENXML(@XMLDOCHANDLE, 'rows/row/peripheral/row/row', 2) WITH (
event_rowguid nvarchar(15) '../../../@rowguid'
,type nvarchar (50) '../@type'
,domain nvarchar (255) '@domain'
,path nvarchar (255) '@path'
,size bigint '@size'
,detail_totaltime decimal (35,0) '@totaltime'
,client int '../../../@client'
) xml
WHERE xml.client = 2 AND xml.size &gt; 0

-- Fill summary content information
INSERT APM.csperipheral
(
cseventid
,type
,totalsize
,totaltime
)
SELECT
e.cseventid
,sync.type
,sync.totalsize
,sync.totaltime
FROM
@PERIPHIAL sync
JOIN
APM.csevent e ON sync.event_rowguid = e.rowguid
WHERE sync.totalsize &gt; 0

SET @INSERTED_ROWCOUNT = @@ROWCOUNT

IF @TRACELEVEL = 4
BEGIN
SELECT @MESSAGE = MESSAGE FROM APM.MESSAGES WHERE ID = 50024
RAISERROR (@MESSAGE, 0, 1, @INSERTED_ROWCOUNT, 'csperipheral') WITH NOWAIT;
END

-- Fill html size
INSERT APM.csperipheral
(
cseventid
,type
,totalsize
)
SELECT DISTINCT
e.cseventid
,N'html'
,sync.htmlSize
FROM
@PERIPHIAL sync
JOIN
csevent e ON sync.event_rowguid = e.rowguid

SET @INSERTED_ROWCOUNT = @@ROWCOUNT

IF @TRACELEVEL = 4
BEGIN
SELECT @MESSAGE = MESSAGE FROM APM.MESSAGES WHERE ID = 50024
RAISERROR (@MESSAGE, 0, 1, @INSERTED_ROWCOUNT, 'csperipheral {html}') WITH NOWAIT;
END

-- Fill detail content information
INSERT APM.csperipheraldetail
(
csperipheralid
,domain
,path
,size
,totaltime
)
SELECT
p.csperipheralid
,sync.domain
,sync.path
,sync.size
,sync.detail_totaltime
FROM
@PERIPHIALDETAIL sync
JOIN
APM.csevent e ON sync.event_rowguid = e.rowguid
JOIN
APM.csperipheral p ON e.cseventid = p.cseventid AND sync.type = p.type

SET @INSERTED_ROWCOUNT = @@ROWCOUNT

IF @TRACELEVEL = 4
BEGIN
SELECT @MESSAGE = MESSAGE FROM APM.MESSAGES WHERE ID = 50024
RAISERROR (@MESSAGE, 0, 1, @INSERTED_ROWCOUNT, 'csperipheraldetail') WITH NOWAIT;
END
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.AjaxCall_sync'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.AjaxCall_sync AS RETURN 1')
END
GO
ALTER PROCEDURE APM.AjaxCall_sync
@XMLDOCHANDLE int
,@PATH nvarchar(100)
,@TRACELEVEL int
AS
BEGIN
SET NOCOUNT ON

DECLARE
@MESSAGE nvarchar(max)
,@RECORDCOUNT int


--------- Fill Ajax call --------

DECLARE @AJAXCALL TABLE (
ajax_call_id int identity(1,1)
,event_rowguid nvarchar(15) collate database_default
,uri nvarchar (255) collate database_default
,networktime decimal (35,0)
,servertime decimal (35,0)
,totaltime decimal (35,0)
,requestsize bigint
,responsesize bigint
,responsetime decimal (35,0)
,handlertime decimal (35,0)
,latency bigint
,utcdate datetime
,SourceName nvarchar (255) collate database_default
)


INSERT INTO @AJAXCALL
(
event_rowguid
,uri
,networktime
,servertime
,totaltime
,requestsize
,responsesize
,responsetime
,handlertime
,latency
,utcdate
,SourceName
)
SELECT
event_rowguid
,uri
,networktime
,servertime
,totaltime
,requestsize
,responsesize
,responsetime
,handlertime
,latency
,utcdate
,SourceName
FROM OPENXML(@XMLDOCHANDLE, @PATH) WITH (
event_rowguid nvarchar(15) '../../@rowguid'
,uri nvarchar (255)
,networktime decimal (35,0)
,servertime decimal (35,0)
,totaltime decimal (35,0)
,requestsize bigint
,responsesize bigint
,responsetime decimal (35,0)
,handlertime decimal (35,0) '../@handlertime'
,latency bigint
,utcdate datetime '../../@utceventdate'
,sourceName nvarchar (255) '../../@source'
) xml

INSERT APM.csajax
(
cseventid
,uri
,networktime
,servertime
,totaltime
,requestsize
,responsesize
,responsetime
,synchronous
,latency
,utcdate
,sourceid
,IsHeaviestNode
)
SELECT
e.cseventid
,sync.uri
,sync.networktime
,sync.servertime
,sync.totaltime
,sync.requestsize
,sync.responsesize
,sync.responsetime
,CASE WHEN handlertime IS NULL THEN 1 ELSE 0 END
,sync.latency
,sync.utcdate
,s.SourceId
,CASE
WHEN sync.ajax_call_id = (SELECT TOP(1) ajax_call_id FROM @AJAXCALL AS a WHERE sync.event_rowguid = a.event_rowguid ORDER BY TotalTime DESC, ajax_call_id)
THEN 1
ELSE 0
END
FROM
@AJAXCALL sync
JOIN
APM.csevent e ON sync.event_rowguid = e.rowguid
JOIN APM.source s ON s.source = sync.SourceName

SELECT @RECORDCOUNT = @@ROWCOUNT

IF @TRACELEVEL = 4
BEGIN
SELECT @MESSAGE = MESSAGE FROM APM.MESSAGES WHERE ID = 50024
RAISERROR (@MESSAGE, 0, 1, @RECORDCOUNT, 'csajax') WITH NOWAIT;
END

---Find Async ajax call-----------

IF EXISTS(SELECT * FROM @AJAXCALL WHERE handlertime IS NOT NULL)
BEGIN
INSERT APM.csasyncajax
(
cseventid
,totaltime
,handlertime
)
SELECT
e.cseventid
,sync.totaltime
,sync.handlertime
FROM
@AJAXCALL sync
JOIN
APM.csevent e ON sync.event_rowguid = e.rowguid
WHERE
sync.handlertime IS NOT NULL

SELECT @RECORDCOUNT = @@ROWCOUNT

IF @TRACELEVEL = 4
BEGIN
SELECT @MESSAGE = MESSAGE FROM APM.MESSAGES WHERE ID = 50024
RAISERROR (@MESSAGE, 0, 1, @RECORDCOUNT, 'csasyncajax') WITH NOWAIT;
END
END
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.JScriptEvent_sync'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.JScriptEvent_sync AS RETURN 1')
END
GO
ALTER PROCEDURE APM.JScriptEvent_sync
@XMLDOCHANDLE int
,@TRACELEVEL int
AS
BEGIN
SET NOCOUNT ON

DECLARE
@INSERTED_ROWCOUNT int
,@MESSAGE nvarchar(max)

DECLARE @SCRIPTEVENT TABLE (
event_rowguid nvarchar(15) collate database_default
,action nvarchar(255) collate database_default
,totaltime nvarchar(255) collate database_default
,utcdate datetime
,SourceName nvarchar (255) collate database_default
)


INSERT @SCRIPTEVENT (
event_rowguid
,action
,totaltime
,utcdate
,SourceName
)
SELECT
event_rowguid
,action
,totaltime
,utcdate
,SourceName
FROM OPENXML(@XMLDOCHANDLE, 'rows/row/jscript') WITH (
event_rowguid nvarchar(15) '../@rowguid'
,action nvarchar(255)
,totaltime decimal (35,0)
,utcdate datetime '../@utceventdate'
,sourceName nvarchar (255) '../@source'
) xml

-- Fill CSJSCRIPTEVENT table--------
INSERT APM.csjscriptevent (
cseventid
,action
,totaltime
,utcdate
,sourceid
)
SELECT
e.cseventid
,sync.action
,sync.totaltime
,sync.utcdate
,s.SourceId
FROM
@SCRIPTEVENT sync
JOIN APM.csevent e ON sync.event_rowguid = e.rowguid
JOIN APM.source s ON s.source = sync.SourceName

SET @INSERTED_ROWCOUNT = @@ROWCOUNT

IF @TRACELEVEL = 4
BEGIN
SELECT @MESSAGE = MESSAGE FROM APM.MESSAGES WHERE ID = 50024
RAISERROR (@MESSAGE, 0, 1, @INSERTED_ROWCOUNT, 'csjscriptevent') WITH NOWAIT;
END
END
GO



IF (OBJECTPROPERTY(OBJECT_ID('APM.ClientEvent_sync'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.ClientEvent_sync AS RETURN 1')
END
GO
/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: ClientEvent_sync */
/* USED IN: Synchronization client event. */
/* Call by Intercept Reporting Services */
/* INPUT PARAMETERS: */
/* @OBJECTKEYXML - xml package syncronization data */
/* @TRACELEVEL - trace level. Reserved. */
/* OUTPUT PARAMETERS: */
/* @ROWNOTAFFECTED - number of records from package which haven't been */
/* synchronized. */
/************************************************************************************/
ALTER PROCEDURE [APM].[ClientEvent_sync]
@OBJECTKEYXML ntext
,@DATABASEID int
,@TRACELEVEL int
,@ROWNOTAFFECTED int output
AS
BEGIN
SET NOCOUNT ON

DECLARE
@MESSAGE nvarchar(max)
,@RECORDCOUNT int

DECLARE
@ERRORIND bit
,@ERRORMESSAGE nvarchar(max)
,@ERRORNUMBER int
,@ERRORSEVERITY int
,@ERRORSTATE int
,@ERRORLINE int
,@ERRORPROCEDURE nvarchar(256)
,@ERRORMESSAGETEXT nvarchar(max)

SET @ERRORIND = 0

BEGIN TRY

SET @ROWNOTAFFECTED = 0

DECLARE
@EXECRESULT int
,@XMLDOCHANDLE int
,@INSERTED_ROWCOUNT int
,@CHANGED_ROWCOUNT int
,@ERROR_MESSAGE nvarchar(max)

--allocate memory for xml package
EXEC @EXECRESULT = sp_xml_preparedocument @XMLDOCHANDLE OUTPUT, @OBJECTKEYXML
IF @EXECRESULT &lt;&gt; 0
BEGIN
SELECT @ERROR_MESSAGE = message FROM APM.messages WHERE id = 50002
RAISERROR(@ERROR_MESSAGE, 16, 1, 'ClientEvent_sync', @EXECRESULT)
END

-----temporary table variable for the keeping xml package
DECLARE @EVENT TABLE (
grouphash nvarchar(50) collate database_default
,source nvarchar(255) collate database_default
,machinename nvarchar(255) collate database_default
,utceventdate datetime
,eventclasstype nvarchar(50) collate database_default
,eventclass nvarchar(50) collate database_default
,description nvarchar(255) collate database_default
,ip nvarchar(50) collate database_default
,subnetc nvarchar(50) collate database_default
,pageuri nvarchar(255) collate database_default
,browser nvarchar(255) collate database_default
,userName nvarchar(255) collate database_default
,rowguid nvarchar(15) collate database_default
,seviewerdbid int
,sevieweregid int
,client int
,pmstatus tinyint
,category nvarchar(50) collate database_default
,rootnodename nvarchar(255) collate database_default
,rootfunction nvarchar(255) collate database_default
)

---- parse and insert xml package to the temporary table variabale
INSERT @EVENT (
grouphash
,source
,machinename
,utceventdate
,eventclasstype
,eventclass
,description
,ip
,subnetc
,pageuri
,browser
,userName
,rowguid
,sevieweregid
,client
,pmstatus
,category
,rootnodename
,rootfunction
)
SELECT
grouphash
,source
,machinename
,utceventdate
,eventclasstype
,eventclass
,description
,ip
,subnetc
,pageuri
,browser
,username
,rowguid
,sevieweregid
,client
,pmstatus
,category
,rootnodename
,rootfunction
FROM OPENXML(@XMLDOCHANDLE, 'rows/row') WITH (
grouphash nvarchar(50)
,source nvarchar(255)
,machinename nvarchar(255)
,utceventdate datetime
,eventclasstype nvarchar(50)
,eventclass nvarchar(50)
,description nvarchar(255)
,ip nvarchar(50)
,subnetc nvarchar(50)
,pageuri nvarchar(255)
,browser nvarchar(255)
,username nvarchar(255)
,rowguid nvarchar(15)
,sevieweregid int
,client int
,pmstatus tinyint
,category nvarchar(50)
,rootnodename nvarchar(255)
,rootfunction nvarchar(255)
) xml

SELECT @RECORDCOUNT = @@ROWCOUNT

--- Trace about package size
IF @TRACELEVEL = 4
BEGIN
SELECT @MESSAGE = MESSAGE FROM APM.MESSAGES WHERE ID = 50024
RAISERROR (@MESSAGE, 0, 1, @RECORDCOUNT, '@EVENT') WITH NOWAIT;
END

UPDATE @EVENT SET seviewerdbid = @DATABASEID

DECLARE @ALLAPPID int
DECLARE @NEWMACHINES TABLE (machineId int)

----- machine can be removed using "Remove computers wizard" so it is need synchronize machines ----
INSERT APM.MACHINE (MACHINE) OUTPUT INSERTED.MACHINEID INTO @NEWMACHINES
SELECT DISTINCT machinename FROM @EVENT e
WHERE NOT EXISTS (SELECT * FROM APM.machine m (NOLOCK) WHERE m.machine = e.machinename)

IF EXISTS(SELECT * FROM @NEWMACHINES)
BEGIN
IF @ALLAPPID IS NULL
SELECT @ALLAPPID = APPLICATIONID FROM APM.APPLICATION (NOLOCK) WHERE APPLICATION = N'All'
---- it is need to create the links with 'All' application group for new sources
INSERT APM.APPLICATIONSOURCEMACHINE
( APPLICATIONID ,
SOURCEID ,
MACHINEID
)
SELECT
@ALLAPPID
,s.SourceId
,m.machineId
FROM
APM.SOURCE (NOLOCK) AS s
CROSS JOIN @NEWMACHINES as m
WHERE
NOT EXISTS
(
SELECT * FROM APM.APPLICATIONSOURCEMACHINE (NOLOCK) AS a
WHERE a.SOURCEID = s.sourceId AND a.APPLICATIONID = @ALLAPPID AND m.machineId = a.machineid
)
END

----- sources can be removed using "Remove applications wizard" so it is need synchronize sources ----
DECLARE @NEWSOURCES TABLE (sourceid int)

----- sources can be removed using "Remove applications wizard" so it is need synchronize sources ----
INSERT APM.SOURCE (SOURCE) OUTPUT INSERTED.SOURCEID INTO @NEWSOURCES
SELECT DISTINCT source FROM @EVENT e
WHERE NOT EXISTS (SELECT * FROM APM.source s (NOLOCK) WHERE s.source = e.source)

IF EXISTS(SELECT * FROM @NEWSOURCES)
BEGIN
IF @ALLAPPID IS NULL
SELECT @ALLAPPID = APPLICATIONID FROM APM.APPLICATION (NOLOCK) WHERE APPLICATION = N'All'
---- it is need to create the links with 'All' application group for new machines
INSERT APM.APPLICATIONSOURCEMACHINE
( APPLICATIONID ,
SOURCEID ,
MACHINEID
)
SELECT
@ALLAPPID
,s.sourceid
,m.machineId
FROM
APM.MACHINE (NOLOCK) AS m
CROSS JOIN @NEWSOURCES as s
WHERE
NOT EXISTS
(
SELECT * FROM APM.APPLICATIONSOURCEMACHINE (NOLOCK) AS a
WHERE a.SOURCEID = s.sourceid AND a.APPLICATIONID = @ALLAPPID AND m.MACHINEid = a.machineid
)
END

-------- sync Users table---------------
INSERT Users (name)
SELECT DISTINCT sync.userName FROM @EVENT sync
WHERE NOT EXISTS(SELECT u.name FROM APM.Users u WHERE sync.userName = u.name)
AND sync.userName IS NOT NULL AND sync.userName &lt;&gt; ''

-- Fill Ip table--------
INSERT APM.ip (ip, subnetc)
SELECT DISTINCT
sync.ip
,sync.subnetc
FROM
@EVENT sync
WHERE
sync.ip IS NOT NULL AND sync.ip &lt;&gt; '' AND NOT EXISTS(SELECT * FROM APM.ip ip WHERE ip.ip = sync.ip)

-- temporary table for traces. It will contains event id of the new events.
CREATE TABLE #STATUSTABLE(EVENTID int, PMSTATUS tinyint)

-- Fill CSEvent table--------
INSERT APM.CSEVENT (
cseventgroupid
,sourceid
,machineid
,utcdate
,classtype
,eventclass
,description
,ipid
,pageuri
,browser
,rowguid
,seviewerdbid
,sevieweregid
,pmstatus
)
OUTPUT INSERTED.csEventId, INSERTED.pmstatus
INTO #STATUSTABLE
SELECT
g.cseventgroupid
,s.sourceid
,m.MACHINEID
,sync.utceventdate
,sync.eventclasstype
,sync.eventclass
,sync.description
,ip.ipid
,sync.pageuri
,sync.browser
,sync.rowguid
,sync.seviewerdbid
,sync.sevieweregid -------- reference to the seviewer event group ---
,sync.pmstatus
FROM
@EVENT sync
JOIN APM.source s ON s.source = sync.source
JOIN APM.CSEventGroup g ON g.hashvalue = sync.grouphash
JOIN APM.MACHINE m ON m.machine = sync.machinename
LEFT JOIN APM.ip ip ON sync.ip = ip.ip
WHERE NOT EXISTS(SELECT * FROM APM.csevent e WHERE sync.rowguid = e.rowguid)
SET @INSERTED_ROWCOUNT = @@ROWCOUNT

--Create event traces for client events
EXEC APM.PMCREATEEVENTTRACES 1, NULL

INSERT APM.CSEVENTDETAIL
(
CSEventId
,Name
,[Value]
,[ValueType]
)
SELECT
e.CSEventId
,'CATEGORY'
,sync.category
,'PM'
FROM
@EVENT AS sync
JOIN APM.CSEvent AS e (NOLOCK) ON sync.rowguid = e.rowguid

INSERT APM.CSEVENTDETAIL
(
CSEventId
,Name
,[Value]
,[ValueType]
)
SELECT
e.CSEventId
,'ROOTNODENAME'
,sync.rootnodename
,'PM'
FROM
@EVENT AS sync
JOIN APM.CSEvent AS e (NOLOCK) ON sync.rowguid = e.rowguid

INSERT APM.CSEVENTDETAIL
(
CSEventId
,Name
,[Value]
,[ValueType]
)
SELECT
e.CSEventId
,'ROOTFUNCTION'
,sync.rootfunction
,'PM'
FROM
@EVENT AS sync
JOIN APM.CSEvent AS e (NOLOCK) ON sync.rowguid = e.rowguid

--------- trace about number of inserted records into csevent table -----------
IF @TRACELEVEL = 4
BEGIN
SELECT @MESSAGE = MESSAGE FROM APM.MESSAGES WHERE ID = 50024
RAISERROR (@MESSAGE, 0, 1, @INSERTED_ROWCOUNT, 'CSEvent') WITH NOWAIT;
END

SELECT @CHANGED_ROWCOUNT = COUNT(*) FROM @EVENT
SET @ROWNOTAFFECTED = @CHANGED_ROWCOUNT - @INSERTED_ROWCOUNT

-----------sync csevent with username------------------
UPDATE e SET
e.userid = u.userid
FROM
APM.csevent e
JOIN @EVENT sync ON sync.rowguid = e.rowguid
JOIN APM.Users u ON sync.userName = u.Name

IF EXISTS(SELECT * FROM @EVENT WHERE client = 2)
BEGIN
IF @TRACELEVEL = 4
BEGIN
SELECT @MESSAGE = MESSAGE FROM APM.MESSAGES WHERE ID = 50025
RAISERROR (@MESSAGE, 0, 1) WITH NOWAIT;
END
----exists pageevents--------
EXECUTE APM.PageEvent_sync @XMLDOCHANDLE, @TRACELEVEL
END

------ Fill ajax calls--------------
EXEC APM.AjaxCall_sync @XMLDOCHANDLE, N'rows/row/ajaxcalls/row', @TRACELEVEL

--------Check Ajax events and script events
IF EXISTS(SELECT * FROM @EVENT WHERE client = 1)
BEGIN
IF @TRACELEVEL = 4
BEGIN
SELECT @MESSAGE = MESSAGE FROM APM.MESSAGES WHERE ID = 50026
RAISERROR (@MESSAGE, 0, 1) WITH NOWAIT;
END
----Find and sync script events --------
EXEC APM.AjaxCall_sync @XMLDOCHANDLE, N'rows/row/jscript/row', @TRACELEVEL
EXECUTE APM.JScriptEvent_sync @XMLDOCHANDLE, @TRACELEVEL
END

-- Update CSEvent table with totaltime, total size and latency values
UPDATE e SET
e.TotalTime = COALESCE(p.TotalTime, COALESCE(js.TotalTime, a.TotalTime)),
e.TotalSize = COALESCE(P.TotalSize, 0) + COALESCE(a.TotalSize, 0),
e.Latency = COALESCE(p.Latency, a.Latency)
FROM
APM.csevent e
JOIN @EVENT sync ON sync.rowguid = e.rowguid
LEFT OUTER JOIN APM.CSPAGEEVENT AS p ON p.CSEventId = e.CSEventId
LEFT OUTER JOIN APM.CSJSCRIPTEVENT AS js ON js.CSEventId = e.CSEventId
OUTER APPLY
(
SELECT
SUM(a.TotalTime) AS TotalTime,
SUM(a.ResponseSize + a.REQUESTSIZE) AS TotalSize,
AVG(a.Latency) AS Latency
FROM
APM.CSAJAX AS a
WHERE
A.CSEventId = e.CSEventId
) AS a

--free memory of xml package
EXEC sp_xml_removedocument @XMLDOCHANDLE

SET @XMLDOCHANDLE = NULL

END TRY
BEGIN CATCH
IF (@@TRANCOUNT &gt; 0)
ROLLBACK TRAN

SELECT
@ERRORNUMBER = ERROR_NUMBER()
,@ERRORSEVERITY = ERROR_SEVERITY()
,@ERRORSTATE = ERROR_STATE()
,@ERRORLINE = ERROR_LINE()
,@ERRORPROCEDURE = ISNULL(ERROR_PROCEDURE(), '-')
,@ERRORMESSAGETEXT = ERROR_MESSAGE()

SET @ERRORIND = 1
END CATCH

IF @XMLDOCHANDLE IS NOT NULL
EXEC sp_xml_removedocument @XMLDOCHANDLE

-- report error if any
IF (@ERRORIND = 1)
BEGIN
DECLARE @ADJUSTEDERRORSEVERITY int

SET @ADJUSTEDERRORSEVERITY = CASE
WHEN @ERRORSEVERITY = 2601 OR @ERRORSEVERITY = 2627 THEN 0
WHEN @ERRORSEVERITY &gt; 18 THEN 18
ELSE @ERRORSEVERITY
END

SELECT @ERROR_MESSAGE = message FROM APM.Messages WHERE id = 50004
RAISERROR (@ERROR_MESSAGE, @ADJUSTEDERRORSEVERITY, 1
,@ERRORNUMBER
,@ERRORSEVERITY
,@ERRORSTATE
,@ERRORPROCEDURE
,@ERRORLINE
,@ERRORMESSAGETEXT
)
END
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.CheckConfiguration'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.CheckConfiguration AS RETURN 1')
END
GO

ALTER PROCEDURE [APM].[CheckConfiguration]
@VERSION nvarchar(15)
,@SCHEMAVERSION nvarchar(15)
,@TRACELEVEL INT
AS
BEGIN
SET NOCOUNT ON;

DECLARE
@ERROR INT

SET @ERROR = 0

IF NOT EXISTS(SELECT * FROM APM.Config WHERE ConfigName = N'DATABASE_VERSION'
AND CAST(ConfigValue AS nvarchar(15)) = @VERSION)
BEGIN
SET @ERROR = 1
GOTO QUIT
END

-- Check that schema is valid
IF NOT EXISTS(SELECT * FROM APM.Config WHERE ConfigName = N'SCHEMA_VERSION'
AND CAST(ConfigValue AS nvarchar(15)) = @SCHEMAVERSION)
BEGIN
SET @ERROR = 1
GOTO QUIT
END


QUIT:
RETURN @ERROR
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.CreateOrUpdateTaskStatus'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.CreateOrUpdateTaskStatus AS RETURN 1')
END
GO

ALTER PROCEDURE APM.CreateOrUpdateTaskStatus
@DATABASEID int
,@TASK nvarchar(50)
,@OPERATION int
,@STATUS nvarchar(50)
,@STARTED bit
,@DATE dateTime
,@LASTTIMESTAMP bigint
,@TRACELEVEL int
,@OPERATIONINDEX bigint OUTPUT
AS
BEGIN
SET NOCOUNT ON;

DECLARE
@RECORDCOUNT int

SELECT
@OPERATIONINDEX = t.LastTimeStamp
FROM
APM.Tasks t
WHERE
t.TableName = @TASK
AND t.SEViewerDbId = @DATABASEID

SELECT @RECORDCOUNT = @@ROWCOUNT

IF @RECORDCOUNT = 1
BEGIN
UPDATE
APM.Tasks
SET Status = @STATUS
,StartDate = CASE WHEN @STARTED = 1 THEN @DATE ELSE StartDate END
,EndDate = CASE WHEN @STARTED = 0 THEN @DATE ELSE EndDate END
,LastTimeStamp = CASE WHEN @STARTED = 0 THEN @LASTTIMESTAMP ELSE LastTimeStamp END
,OperationId = @OPERATION
WHERE
TableName = @TASK
AND SEViewerDbId = @DATABASEID
IF @STARTED = 0
Set @OPERATIONINDEX = @LASTTIMESTAMP
END
IF @RECORDCOUNT = 0
BEGIN
INSERT
APM.Tasks (TableName, StartDate, OperationId, LastTimeStamp, Status, SEViewerDbId)
VALUES (
@TASK
,@DATE
,@OPERATION
,0
,@STATUS
,@DATABASEID
)
SET @OPERATIONINDEX = 0
END
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.SelectAbsDateORRelative'), 'IsScalarFunction') IS NULL)
BEGIN
EXECUTE('CREATE FUNCTION APM.SelectAbsDateORRelative ()
RETURNS int
AS begin return 1 end')
END
GO

ALTER FUNCTION APM.SelectAbsDateORRelative(
@RELATIVEDATE INT,
@ABSDATE DATETIME,
--@ISENDDATE parameter defines how to return relative date
--if @ISENDDATE = 1, then appropriate date returned with 23:59 hours, otherwise it would be rounded to 00:00
@ISENDDATE BIT,
--Offset field is used to return time value in client timezone, it can be different from SQL server
@OFFSET INT) RETURNS DATETIME
AS
BEGIN
DECLARE @RESULTDATE DATETIME
-- Current time in user timezone
DECLARE @CURRENTUSERDATE DATETIME
SELECT @CURRENTUSERDATE = DATEADD(minute, @OFFSET, GETUTCDATE())

IF @RELATIVEDATE &lt;&gt; 0
BEGIN
SELECT @RESULTDATE =
CASE @RELATIVEDATE
-- This Week: First Day
WHEN 10 THEN DATEADD(d, -(DATEPART(WEEKDAY, @CURRENTUSERDATE) - 1), @CURRENTUSERDATE)
-- This Week: Last Day
WHEN 20 THEN DATEADD(d, (7 - DATEPART(WEEKDAY, @CURRENTUSERDATE)), @CURRENTUSERDATE)
-- Previous Week: First Day
WHEN 30 THEN DATEADD(WEEK, -1, DATEADD(d, -(DATEPART(WEEKDAY, @CURRENTUSERDATE) - 1), @CURRENTUSERDATE))
-- Previous Week: Last Day
WHEN 40 THEN DATEADD(WEEK, -1, DATEADD(d, (7 - DATEPART(WEEKDAY, @CURRENTUSERDATE)), @CURRENTUSERDATE))
-- This Month: First Day
WHEN 50 THEN DATEADD(DAY, -(DATEPART(DAY, @CURRENTUSERDATE) - 1), @CURRENTUSERDATE)
-- This Month: Last Day
WHEN 60 THEN DATEADD(d, -DATEPART(DAY, DATEADD(MONTH, 1, @CURRENTUSERDATE)), DATEADD(MONTH, 1, @CURRENTUSERDATE))
-- Previous Month: First Day
WHEN 70 THEN DATEADD(MONTH, -1, DATEADD(DAY, -(DATEPART(DAY, @CURRENTUSERDATE) - 1), @CURRENTUSERDATE))
-- Previous Month: Last Day
WHEN 80 THEN DATEADD(DAY, -DATEPART(DAY, @CURRENTUSERDATE), @CURRENTUSERDATE)
-- Today
WHEN 90 THEN @CURRENTUSERDATE
-- Yesterday
WHEN 100 THEN DATEADD(DAY, -1, @CURRENTUSERDATE)
-- Tomorrow
WHEN 110 THEN DATEADD(DAY, 1, @CURRENTUSERDATE)
END
--Round datetime to date, without hours
SELECT @RESULTDATE = CONVERT(NVARCHAR, @RESULTDATE, 112)

IF @ISENDDATE &gt; 0
BEGIN
--If IsEndDate parameter specified, take all day (time value equal to 23:59:59)
SELECT @RESULTDATE = DATEADD(second, -1, DATEADD(d, 1, @RESULTDATE))
IF @RESULTDATE &gt; @CURRENTUSERDATE
SELECT @RESULTDATE = DATEADD(HOUR, DATEPART(HOUR,@CURRENTUSERDATE)+1, CONVERT(NVARCHAR, @CURRENTUSERDATE, 112))
END
END
ELSE
SELECT @RESULTDATE =@ABSDATE

RETURN @RESULTDATE
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.EventDetail_sync'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.EventDetail_sync AS RETURN 1')
END
GO

ALTER PROCEDURE APM.EventDetail_sync
@OBJECTKEYXML ntext
,@TRACELEVEL INT
,@ROWNOTAFFECTED int output
AS
BEGIN
SET NOCOUNT ON

DECLARE
@ERRORIND bit
,@ERRORMESSAGE nvarchar(max)
,@ERRORNUMBER int
,@ERRORSEVERITY int
,@ERRORSTATE int
,@ERRORLINE int
,@ERRORPROCEDURE nvarchar(256)
,@ERRORMESSAGETEXT nvarchar(max)

SET @ERRORIND = 0

BEGIN TRY

DECLARE
@EXECRESULT int
,@XMLDOCHANDLE int
,@ERROR_MESSAGE nvarchar(max)
,@INSERTED_ROWCOUNT int
,@UPDATED_ROWCOUNT int
,@CHANGEDROWCOUNT int

SET @ROWNOTAFFECTED = 0

EXEC @EXECRESULT = sp_xml_preparedocument @XMLDOCHANDLE OUTPUT, @OBJECTKEYXML
IF @EXECRESULT &lt;&gt; 0
BEGIN
SELECT @ERROR_MESSAGE = message FROM APM.messages WHERE id = 50002
RAISERROR(@ERROR_MESSAGE, 16, 1, 'EventDetail_sync', @EXECRESULT)
END

DECLARE @EVENTDETAIL TABLE (
eventrowguid nvarchar(15) collate database_default
,name nvarchar(50) collate database_default
,val1 nvarchar(255) collate database_default
,val2 nvarchar(255) collate database_default
,client bit
)

INSERT @EVENTDETAIL (
eventrowguid
,name
,val1
,val2
,client
)
SELECT
eventrowguid
,name
,val1
,val2
,client
FROM OPENXML(@XMLDOCHANDLE, 'rows/row', 2) WITH (
eventrowguid nvarchar(15)
,name nvarchar(50)
,val1 nvarchar(255)
,val2 nvarchar(255)
,client bit
) xml


EXEC sp_xml_removedocument @XMLDOCHANDLE

SET @XMLDOCHANDLE = NULL

-- Fill Ip table--------
INSERT APM.ip (ip, subnetc)
SELECT DISTINCT
sync.val1
,sync.val2
FROM
@EVENTDETAIL sync
WHERE
sync.name = 'IPADDRESS' AND
sync.val1 IS NOT NULL AND sync.val1 &lt;&gt; '' AND NOT EXISTS(SELECT * FROM APM.ip ip WHERE ip.ip = sync.val1)

UPDATE e
SET e.ipid = ip.ipid
FROM
APM.Event e
JOIN @EVENTDETAIL sync ON e.rowguid = sync.eventrowguid AND sync.name = 'IPADDRESS' and sync.client = 0
JOIN APM.Ip ip ON sync.val1 = ip.ip


SET @UPDATED_ROWCOUNT = @@ROWCOUNT

SELECT @CHANGEDROWCOUNT = COUNT(*) FROM @EVENTDETAIL WHERE name = 'IPADDRESS' AND client = 0

SET @ROWNOTAFFECTED = @CHANGEDROWCOUNT - @UPDATED_ROWCOUNT
END TRY
BEGIN CATCH
IF (@@TRANCOUNT &gt; 0)
ROLLBACK TRAN

SELECT
@ERRORNUMBER = ERROR_NUMBER()
,@ERRORSEVERITY = ERROR_SEVERITY()
,@ERRORSTATE = ERROR_STATE()
,@ERRORLINE = ERROR_LINE()
,@ERRORPROCEDURE = ISNULL(ERROR_PROCEDURE(), '-')
,@ERRORMESSAGETEXT = ERROR_MESSAGE()

SET @ERRORIND = 1
END CATCH

IF @XMLDOCHANDLE IS NOT NULL
EXEC sp_xml_removedocument @XMLDOCHANDLE

-- report error if any
IF (@ERRORIND = 1)
BEGIN
DECLARE @ADJUSTEDERRORSEVERITY int

SET @ADJUSTEDERRORSEVERITY = CASE
WHEN @ERRORSEVERITY = 2601 OR @ERRORSEVERITY = 2627 THEN 0
WHEN @ERRORSEVERITY &gt; 18 THEN 18
ELSE @ERRORSEVERITY
END
SELECT @ERROR_MESSAGE = message FROM APM.Messages WHERE id = 50004
RAISERROR (@ERROR_MESSAGE, @ADJUSTEDERRORSEVERITY, 1
,@ERRORNUMBER
,@ERRORSEVERITY
,@ERRORSTATE
,@ERRORPROCEDURE
,@ERRORLINE
,@ERRORMESSAGETEXT
)
END
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.GetDependentComputersList'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.GetDependentComputersList AS RETURN 1')
END
GO

ALTER PROCEDURE APM.GetDependentComputersList
@SOURCE NVARCHAR(MAX)
,@COMPUTERS NVARCHAR(MAX)
,@STARTDATE DateTime
,@ENDDATE DateTime
AS
BEGIN
CREATE TABLE #SOURCEMACHINEMULTIVALUE
(
TYPEID int, VALUE int
)
INSERT
INTO #SOURCEMACHINEMULTIVALUE
SELECT
p.typeid,
CAST(p.value AS Int)
FROM
APM.GetMultiParameters(@SOURCE, @COMPUTERS) p
--Select machine for server events
SELECT DISTINCT m.machine, m.machineid
FROM
APM.Machine AS m (NOLOCK)
JOIN #SOURCEMACHINEMULTIVALUE AS f2 ON (f2.TYPEID = 2 and f2.VALUE = M.machineid)
UNION
--Computer parameter have to contain at leat one value, or an exception occures in reports
select N'', -1
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.ApplicationStatusSummaryStatistics'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.ApplicationStatusSummaryStatistics AS RETURN 1')
END
GO

/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: ApplicationStatusSummaryStatistics */
/* USED IN: Application Status Report */
/* INPUT PARAMETERS: */
/* @SOURCEIDS - List of the source id, separated by comma. Exp: '1,2,3' */
/* @COMPUTERIDS - List of the computer id, separated by comma. Exp: '1,2,3' */
/* @ENDDATE - End date of the period */
/* @PERIOD - Period type(Day, Week or Month). */
/* - Use for the Start Date calculate of the period */
/* @AVERAGEINTERVAL- This value specifies interval, for which average values */
/* be calculated. Possible values: 1(1 month), 2(2 month), */
/* 3(3 month), 6(6 month), 17 (7 day) */
/* @TRESHOLD - Event duration treshold */
/* @PROBLEM - Event problem type (all, critical) */
/* @TIMEZONE - correlate parameter (timezone by min) */
/* - for the End Date calculate */
/************************************************************************************/
ALTER PROCEDURE APM.ApplicationStatusSummaryStatistics
@SOURCEIDS NVARCHAR(MAX),
@COMPUTERIDS NVARCHAR(MAX),
@ENDDATE DATETIME,
@PERIOD INT,
@AVERAGEINTERVAL INT,
@THRESHOLD INT,
@PROBLEM NVARCHAR(10),
@TIMEZONE INT,
@PMSTATUS NVARCHAR(50)
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON;

/************************************************************************************/
/* Prepare auxiliary variables for the further calculation */
/************************************************************************************/

--Calculate End Date in view of timezone
SET @ENDDATE = DATEADD(minute, -@TIMEZONE, @ENDDATE)

--Used for counting average value for last three months
DECLARE @PERIODDAYSCOUNT int
SET @PERIODDAYSCOUNT = APM.GetQueryDateCount(@PERIOD, @ENDDATE)

--Calculate Start Date in view of period type
DECLARE @STARTDATE DateTime
SET @STARTDATE = DATEADD(d, -@PERIODDAYSCOUNT, @ENDDATE)

--Calculate previos period Start Date
DECLARE @LASTPERIODSTARTDATE DateTime
SET @LASTPERIODSTARTDATE = DATEADD(d, -@PERIODDAYSCOUNT, @STARTDATE)

--Calculate average period Start Date
DECLARE @AVERAGEPERIODSTARTDATE DateTime
SET @AVERAGEPERIODSTARTDATE = (CASE
WHEN @AVERAGEINTERVAL &lt; 10 THEN DATEADD(month, -@AVERAGEINTERVAL, @STARTDATE)
ELSE DATEADD(day, -(@AVERAGEINTERVAL-10), @STARTDATE)
END)

DECLARE @PROCESSORCOUNTERID INT
SELECT @PROCESSORCOUNTERID = PCtypeId FROM APM.PCType (NOLOCK) WHERE type = N'\Process\% Processor Time'

DECLARE @MEMORYCOUNTERID INT
SELECT @MEMORYCOUNTERID = PCtypeId FROM APM.PCType (NOLOCK) WHERE type = N'\Process\Private Bytes'

DECLARE @IOCOUNTERID INT
SELECT @IOCOUNTERID = PCtypeId FROM APM.PCType (NOLOCK) WHERE type = N'\Process\IO Data Bytes/sec'

DECLARE @MONITOREDREQUESTCOUNTERID INT
SELECT @MONITOREDREQUESTCOUNTERID = PCtypeId FROM APM.PCType (NOLOCK) WHERE type = N'\Apps\Monitored Requests'

DECLARE @REQUESTTIMECOUNTERID INT
SELECT @REQUESTTIMECOUNTERID = PCtypeId FROM APM.PCType (NOLOCK) WHERE type = N'\Apps\Avg. Request Time'

/************************************************************************************/
/* ASSISTING TEMP TABLES */
/************************************************************************************/

-- Filter table, which contains machine ids and source ids
-- typeid defines filter type - 1 for source and 2 for machine
-- valueId filter value - source id and machine id
CREATE TABLE #SOURCEMACHINEFILTERTABLE(
TYPEID INT,
VALUEID INT
)

-- Fill table #SOURCEMACHINEFILTERTABLE
INSERT
INTO #SOURCEMACHINEFILTERTABLE
SELECT
p.typeId AS TYPEID,
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@SOURCEIDS, @COMPUTERIDS) AS p

-- Filter table, which contains PM Statuses of Events
CREATE TABLE #PMSTATUSFILTERTABLE(
VALUEID INT
)

-- Fill table #PMSTATUSFILTERTABLE
INSERT
INTO #PMSTATUSFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@PMSTATUS, N'') AS p

/************************************************************************************/
/* Filtered events for further manipulations */
/************************************************************************************/
;WITH GetSummaryStatistics_EventsFiltered AS
(
SELECT
e.SourceId,
e.EventId,
e.UtcEventDate AS Date,
ABS(DATEDIFF(d, DATEADD(minute, @TIMEZONE, e.UtcEventDate), @ENDDATE)) / @PERIODDAYSCOUNT AS PeriodId
FROM
APM.Event AS e
JOIN #SOURCEMACHINEFILTERTABLE AS f1 ON (f1.TYPEID = 1 AND f1.VALUEID = e.SourceId)
JOIN #SOURCEMACHINEFILTERTABLE AS f2 ON (f2.TYPEID = 2 AND f2.VALUEID = e.MachineId)
JOIN #PMSTATUSFILTERTABLE AS f3 ON (f3.VALUEID = e.PMStatus)
WHERE
(e.EventClassType = N'exception' OR (e.EventClassType = 'performance' AND e.eventduration / 1000000.0 &gt;= @THRESHOLD))
AND (e.category LIKE @PROBLEM OR e.category IS NULL)
AND e.utceventdate &gt;= @AVERAGEPERIODSTARTDATE
AND e.utceventdate &lt; @ENDDATE
AND (e.HeavyLight &lt;&gt; 0 OR e.HeavyLight IS NULL)

),

/************************************************************************************/
/* Resource Utilizayion Queries */
/************************************************************************************/
-- Calculate resource utilization by Source in one hour.
-- Aggregation between instances should be done here (for cases when one source run in several process in one hour)
SourceHourlyResourceUtilization AS
(
SELECT
ph.MachineId,
ph.SourceId,
ph.UTCDate,
ph.PCTypeId AS [Type],

---------- Pivot instance count by period type -----------
(CASE
WHEN ph.UtcDate &gt;= @LASTPERIODSTARTDATE AND ph.UtcDate &lt; @STARTDATE
THEN SUM(ph.SampleCount)*1.0/MAX(ph.PackageCounter)
END) AS LastInstanceCount,
(CASE
WHEN ph.UtcDate &gt;= @STARTDATE AND ph.UtcDate &lt; @ENDDATE
THEN SUM(ph.SampleCount)*1.0/MAX(ph.PackageCounter)
END) AS CurInstanceCount,
(CASE
WHEN ph.utcdate &gt;= @AVERAGEPERIODSTARTDATE AND ph.utcdate &lt; @STARTDATE
THEN SUM(ph.SampleCount)*1.0/MAX(ph.PackageCounter)
END) AS AvgInstanceCount,

---------- Pivot resource value by period type -----------
(CASE
WHEN ph.UtcDate &gt;= @LASTPERIODSTARTDATE AND ph.UtcDate &lt; @STARTDATE THEN SUM(SumValue)/SUM(SampleCount)
END) AS LastValue,
(CASE
WHEN ph.UtcDate &gt;= @STARTDATE AND ph.UtcDate &lt; @ENDDATE THEN SUM(SumValue)/SUM(SampleCount)
END) AS CurValue,
(CASE
WHEN ph.utcdate &gt;= @AVERAGEPERIODSTARTDATE AND ph.utcdate &lt; @STARTDATE THEN SUM(SumValue)/SUM(SampleCount)
END) AS AvgValue,

ABS(DATEDIFF(day, DATEADD(minute, @TIMEZONE, ph.utcdate), @ENDDATE)) / @PERIODDAYSCOUNT AS PeriodId
FROM
APM.PerfHourly AS ph (NOLOCK)
--Join with #SOURCEMACHINEFILTERTABLE with typeId = 1 provides filtering perfHourly by sourceid
JOIN #SOURCEMACHINEFILTERTABLE AS f1 ON (f1.TYPEID = 1 AND f1.VALUEID = ph.SourceId)
--Join with #SOURCEMACHINEFILTERTABLE with typeId = 2 provides filtering perfHourly by machineid
JOIN #SOURCEMACHINEFILTERTABLE AS f2 ON (f2.TYPEID = 2 AND f2.VALUEID = ph.MachineId)
WHERE
ph.UTCDate &gt;= @AVERAGEPERIODSTARTDATE
AND ph.UTCDate &lt; @ENDDATE
AND ph.PCTypeId IN (@PROCESSORCOUNTERID, @IOCOUNTERID, @MEMORYCOUNTERID)
GROUP BY
ph.MachineId,
ph.SourceId,
ph.UTCDate,
ph.PCTypeId
),
--Calculate average application resource utilization over all specified period per machine
--and for specified grouping period
ApplicationResourceUtilizationByMachines AS
(
SELECT
ph.MachineId,
ph.SourceId,
ph.PeriodId,
-- Instance count should be same for different resource types in one hour for one process
-- and averaging them won't make any difference but allow to avoid one aggregation step
AVG(ph.CurInstanceCount) AS CurInstanceCount,
AVG(ph.LastInstanceCount) AS LastInstanceCount,
AVG(ph.AvgInstanceCount) AS AvgInstanceCount,

---------- Pivot resource by counter type -----------

----------- 'Process% Processor Time' counter -------------------
AVG(CASE WHEN ph.type = @PROCESSORCOUNTERID THEN ph.CurValue END) AS CurCPUSum,
AVG(CASE WHEN ph.type = @PROCESSORCOUNTERID THEN ph.LastValue END) AS LastCPUSum,
AVG(CASE WHEN ph.type = @PROCESSORCOUNTERID THEN ph.AvgValue END) AS AvgCPUSum,

----------- 'ProcessPrivate Bytes' counter -------------------
AVG(CASE WHEN ph.type = @MEMORYCOUNTERID THEN ph.CurValue END) AS CurMemSum,
AVG(CASE WHEN ph.type = @MEMORYCOUNTERID THEN ph.LastValue END) AS LastMemSum,
AVG(CASE WHEN ph.type = @MEMORYCOUNTERID THEN ph.AvgValue END) AS AvgMemSum,

----------- 'ProcessIO Data Bytes/sec' counter -------------------
AVG(CASE WHEN ph.type = @IOCOUNTERID THEN ph.CurValue END) AS CurIOSum,
AVG(CASE WHEN ph.type = @IOCOUNTERID THEN ph.LastValue END) AS LastIOSum,
AVG(CASE WHEN ph.type = @IOCOUNTERID THEN ph.AvgValue END) AS AvgIOSum
FROM
SourceHourlyResourceUtilization AS ph
GROUP BY
ph.MachineId,
ph.SourceId,
ph.PeriodId
),
-- Count Monitored Requests and Avg. Request Timefor Application on each machine
-- as source can run on different machines with same process name and app pool, but different sources set,
-- it is important to group by machine to, to avoid calculation of requests from the other app pool
-- Summarize request count in each period (PeriodId differs only for AvgValue)
ApplicationNetAppCountersByMachinePrepare AS
(
SELECT
ph.MachineId,
ph.SourceId,
----------------- Pivot Monitor Request Counter by period ------------------
CASE WHEN ph.UtcDate &gt;= @LASTPERIODSTARTDATE AND ph.UtcDate &lt; @STARTDATE
THEN SUM(CASE WHEN ph.PCTypeID = @MONITOREDREQUESTCOUNTERID THEN ph.SumValue END)
END AS LastMonRequest,
CASE WHEN ph.UtcDate &gt;= @STARTDATE AND ph.UtcDate &lt; @ENDDATE
THEN SUM(CASE WHEN ph.PCTypeID = @MONITOREDREQUESTCOUNTERID THEN ph.SumValue END)
END AS CurMonRequest,
CASE WHEN ph.utcdate &gt;= @AVERAGEPERIODSTARTDATE AND ph.utcdate &lt; @STARTDATE
THEN SUM(CASE WHEN ph.PCTypeID = @MONITOREDREQUESTCOUNTERID THEN ph.SumValue END)
END AS AvgMonRequest,

----------------- Pivot Avg. Request Time Counter by period ------------------
CASE WHEN ph.UtcDate &gt;= @LASTPERIODSTARTDATE AND ph.UtcDate &lt; @STARTDATE
THEN AVG(CASE WHEN ph.PCTypeID = @REQUESTTIMECOUNTERID THEN ph.SumValue / ph.SampleCount END)
END AS LastAvgReqTime,
CASE WHEN ph.UtcDate &gt;= @STARTDATE AND ph.UtcDate &lt; @ENDDATE
THEN AVG(CASE WHEN ph.PCTypeID = @REQUESTTIMECOUNTERID THEN ph.SumValue / ph.SampleCount END)
END AS CurAvgReqTime,
CASE WHEN ph.utcdate &gt;= @AVERAGEPERIODSTARTDATE AND ph.utcdate &lt; @STARTDATE
THEN AVG(CASE WHEN ph.PCTypeID = @REQUESTTIMECOUNTERID THEN ph.SumValue / ph.SampleCount END)
END AS AvgReqTime,

ABS(DATEDIFF(day, DATEADD(minute, @TIMEZONE, ph.utcdate), @ENDDATE)) / @PERIODDAYSCOUNT AS PeriodId
FROM
APM.PerfHourly AS ph (NOLOCK)
--Join with #SOURCEMACHINEFILTERTABLE provides filtering perfHourly by sourceid
JOIN #SOURCEMACHINEFILTERTABLE AS f1 ON (f1.TYPEID = 1 AND ph.SourceId = f1.VALUEID)
--Join with #SOURCEMACHINEFILTERTABLE provides filtering perfHourly by machineid
JOIN #SOURCEMACHINEFILTERTABLE AS f2 ON (f2.TYPEID = 2 AND f2.VALUEID = ph.MachineId)
WHERE
ph.UTCDate &gt;= @AVERAGEPERIODSTARTDATE
AND ph.UTCDate &lt; @ENDDATE
AND ph.PCTypeID IN (@REQUESTTIMECOUNTERID, @MONITOREDREQUESTCOUNTERID)
GROUP BY
ph.MachineId,
ph.SourceId,
ph.UTCDate
),
--Calculate average request time and sum request count for specified grouping period
ApplicationNetAppCountersByMachine AS
(
SELECT
ph.MachineId,
ph.SourceId,
ph.PeriodId,
SUM(ph.LastMonRequest) AS LastMonRequest,
SUM(ph.CurMonRequest) AS CurMonRequest,
SUM(ph.AvgMonRequest) AS AvgMonRequest,
AVG(ph.LastAvgReqTime) AS LastAvgReqTime,
AVG(ph.CurAvgReqTime) AS CurAvgReqTime,
AVG(ph.AvgReqTime) AS AvgReqTime
FROM
ApplicationNetAppCountersByMachinePrepare ph
GROUP BY
ph.MachineId,
ph.SourceId,
ph.PeriodId
),
--Union .NET counters and process counters for period Id.
--PeriodId differs only for average, so for current and last period it doesn't matter which agg function is taken
ActivePreparePCounters AS (
SELECT
pc.machineId,
pc.SourceId,

MAX(netApp.CurMonRequest) AS CurReqCount,
MAX(netApp.LastMonRequest) AS LastReqCount,
AVG(netApp.AvgMonRequest) AS AvgReqCount,

MAX(netApp.CurAvgReqTime) AS CurAvgReqTime,
MAX(netApp.LastAvgReqTime) AS LastAvgReqTime,
AVG(netApp.AvgReqTime) AS AvgReqTime,

MAX(pc.CurInstanceCount) AS CurInstanceCount,
MAX(pc.LastInstanceCount) AS LastInstanceCount,
AVG(pc.AvgInstanceCount) AS AvgInstanceCount,

MAX(pc.CurCPUSum) AS CurCPUSum,
MAX(pc.LastCPUSum) AS LastCPUSum,
AVG(pc.AvgCPUSum) AS AvgCPUSum,

MAX(pc.CurMemSum) AS CurMemSum,
MAX(pc.LastMemSum) AS LastMemSum,
AVG(pc.AvgMemSum) AS AvgMemSum,

MAX(pc.CurIOSum) AS CurIOSum,
MAX(pc.LastIOSum) AS LastIOSum,
AVG(pc.AvgIOSum) AS AvgIOSum
FROM
ApplicationResourceUtilizationByMachines AS pc
LEFT JOIN ApplicationNetAppCountersByMachine AS netApp ON netApp.MachineId = pc.MachineId
AND netApp.SourceId = pc.SourceId AND netApp.PeriodId = netApp.PeriodId
GROUP BY
pc.machineId,
pc.SourceId
),
--Group PC between machines
PCounters AS
(
SELECT
pc.SourceId AS SourceId,
SUM(pc.CurReqCount) AS CurReqCount,
SUM(pc.LastReqCount) AS LastReqCount,
SUM(pc.AvgReqCount) AS AvgReqCount,
AVG(pc.CurAvgReqTime) AS CurAvgReqTime,
AVG(pc.LastAvgReqTime) AS LastAvgReqTime,
AVG(pc.AvgReqTime) AS AvgReqTime,
AVG(pc.CurCPUSum / COALESCE(m.CPUCount, 1)) AS CurCPUSum,
AVG(pc.LastCPUSum / COALESCE(m.CPUCount, 1)) AS LastCPUSum,
AVG(pc.AvgCPUSum / COALESCE(m.CPUCount, 1)) AS AvgCPUSum,
AVG(pc.CurMemSum) AS CurMemSum,
AVG(pc.LastMemSum) AS LastMemSum,
AVG(pc.AvgMemSum) AS AvgMemSum,
AVG(pc.CurIOSum) AS CurIOSum,
AVG(pc.LastIOSum) AS LastIOSum,
AVG(pc.AvgIOSum) AS AvgIOSum,
AVG(pc.CurInstanceCount) AS CurInstanceCount,
AVG(pc.LastInstanceCount) AS LastInstanceCount,
AVG(pc.AvgInstanceCount) AS AvgInstanceCount
FROM
ActivePreparePCounters AS pc
JOIN APM.Machine AS m ON m.MachineId = pc.MachineId
GROUP BY
pc.SourceId
),
PrepareEvents AS
(
SELECT
e.SourceId,
e.PeriodId,
COUNT(CASE WHEN e.date &gt;= @STARTDATE AND e.date &lt; @ENDDATE THEN e.eventid END) AS CurEventCount,
COUNT(CASE WHEN e.date &gt;= @LASTPERIODSTARTDATE AND e.date &lt; @STARTDATE THEN e.eventid END) AS LastEventCount,
COUNT(CASE WHEN e.date &lt; @STARTDATE THEN e.eventid END) AS AverageEventCount
FROM
GetSummaryStatistics_EventsFiltered AS e
GROUP BY
e.SourceId,
e.PeriodId
),
--Aggregate average event count. As PeriodId differs only for avg value, it doesn't matter which aggregation function is taken for other values
Events AS
(
SELECT
e.SourceId,
MAX(e.CurEventCount) AS CurEventCount,
MAX(e.LastEventCount) AS LastEventCount,
--Average counting should not include current period
AVG(CASE WHEN PeriodID &gt; 0 THEN e.AverageEventCount END) AS AverageEventCount
FROM
PrepareEvents AS e
GROUP BY
e.SourceId
),
-- this query separated from GetSummaryStatistics_EventsFiltered as it has smaller period
GetSummaryStatistics_EventsProblemsFiltered AS
(
SELECT
e.SourceId,
e.EventId,
e.EventClassType,
e.Description,
e.RootNodeName,
--Forms description for perfNode this way to avoid duration in event description
COALESCE(RIGHT(pn.Description, LEN(pn.Description) - CHARINDEX(':', pn.Description)), N'') AS PerfNode,
e.UtcEventDate AS Date,
eg.FirstEventDate
FROM
APM.Event AS e
JOIN APM.EventGroup AS eg ON e.eventgroupId = eg.EventGroupId
JOIN #SOURCEMACHINEFILTERTABLE AS f1 ON (f1.TYPEID = 1 AND f1.VALUEID = e.SourceId)
JOIN #SOURCEMACHINEFILTERTABLE AS f2 ON (f2.TYPEID = 2 AND f2.VALUEID = e.MachineId)
JOIN #PMSTATUSFILTERTABLE AS f3 ON (f3.VALUEID = e.PMStatus)
OUTER APPLY (
SELECT TOP(1)
pn.description
FROM
APM.PerformanceNode AS pn
WHERE
pn.eventid = e.eventid AND e.resourceid = pn.resourceid
ORDER BY
pn.selfduration DESC
) AS pn
WHERE
(e.EventClassType = N'exception' OR (e.EventClassType = 'performance' AND e.eventduration / 1000000.0 &gt;= @THRESHOLD))
AND (e.category LIKE @PROBLEM OR e.category IS NULL)
AND e.utceventdate &gt;= @LASTPERIODSTARTDATE
AND e.utceventdate &lt; @ENDDATE
AND (e.HeavyLight &lt;&gt; 0 OR e.HeavyLight IS NULL)

),
EventProblems AS
(
SELECT
e.SourceId,
COUNT(DISTINCT CASE WHEN (EventClassType = 'Performance' AND e.date &gt;= @STARTDATE AND e.date &lt; @ENDDATE) THEN rootnodeName + perfNode END) AS CurPerformanceProblemCount,
COUNT(DISTINCT CASE WHEN (EventClassType &lt;&gt; 'Performance' AND e.date &gt;= @STARTDATE AND e.date &lt; @ENDDATE) THEN e.description END) AS CurExceptionProblemCount,
COUNT(CASE WHEN (EventClassType = 'Performance' AND e.date &gt;= @STARTDATE AND e.date &lt; @ENDDATE) THEN e.eventid END) AS CurPerformanceEventCount,
COUNT(CASE WHEN (EventClassType &lt;&gt; 'Performance' AND e.date &gt;= @STARTDATE AND e.date &lt; @ENDDATE) THEN e.eventid END) AS CurExceptionEventCount,
COUNT(DISTINCT CASE WHEN (EventClassType = 'Performance' AND e.date &gt;= @LASTPERIODSTARTDATE AND e.date &lt; @STARTDATE) THEN rootnodeName + perfNode END) AS LastPerformanceProblemCount,
COUNT(DISTINCT CASE WHEN (EventClassType &lt;&gt; 'Performance' AND e.date &gt;= @LASTPERIODSTARTDATE AND e.date &lt; @STARTDATE) THEN e.description END) AS LastExceptionProblemCount,
COUNT(CASE WHEN (EventClassType = 'Performance' AND e.date &gt;= @LASTPERIODSTARTDATE AND e.date &lt; @STARTDATE) THEN e.eventid END) AS LastPerformanceEventCount,
COUNT(CASE WHEN (EventClassType &lt;&gt; 'Performance' AND e.date &gt;= @LASTPERIODSTARTDATE AND e.date &lt; @STARTDATE) THEN e.eventid END) AS LastExceptionEventCount,
COUNT(DISTINCT CASE WHEN (e.EventClassType = 'performance' AND e.firsteventdate &gt;= @STARTDATE) THEN e.rootnodeName + perfNode END) as NewPerfProblemsCount,
COUNT(DISTINCT CASE WHEN (e.EventClassType &lt;&gt; 'performance' AND e.firsteventdate &gt;= @STARTDATE) THEN e.description END) as NewExpProblemsCount
FROM
GetSummaryStatistics_EventsProblemsFiltered AS e
GROUP BY
e.SourceId
),
ResultQuery AS
(
SELECT
ROW_NUMBER() OVER(ORDER BY s.SourceId) AS Id,
s.SourceId,
s.Source,
COALESCE(pc.CurReqCount, 0) AS CurMonitoredRequestSum,
COALESCE(pc.LastReqCount, 0) AS LastMonitoredRequestSum,
COALESCE(pc.AvgReqCount, 0) AS AvgMonitoredRequestSum,
COALESCE(pc.CurAvgReqTime, 0) AS CurAvrValue,
COALESCE(pc.LastAvgReqTime, 0) AS LastAvgValue,
COALESCE(pc.AvgReqTime, 0) AS AvgValue,
COALESCE(pc.CurCPUSum, 0) AS CurCPUValue,
COALESCE(pc.LastCPUSum, 0) AS LastCPUValue,
COALESCE(pc.AvgCPUSum, 0) AS CPUAvgValue,
COALESCE(pc.CurMemSum, 0) AS CurMemValue,
COALESCE(pc.LastMemSum, 0) AS LastMemValue,
COALESCE(pc.AvgMemSum, 0) AS MemAvgValue,
COALESCE(pc.CurIOSum, 0) AS CurIOValue,
COALESCE(pc.LastIOSum, 0) AS LastIOValue,
COALESCE(pc.AvgIOSum, 0) AS IOAvgValue,

COALESCE(pc.CurInstanceCount, 0) AS CurInstanceCount,
COALESCE(pc.LastInstanceCount, 0) AS LastInstanceCount,
COALESCE(pc.AvgInstanceCount, 0) AS AvgInstanceCount,

COALESCE(E.LastEventCount, 0) AS LastEventCount,
COALESCE(e.CurEventCount, 0) AS CurrentEventCount,
COALESCE(e.AverageEventCount, 0) AS AvgEventsCount,

COALESCE(p.CurExceptionEventCount, 0) AS CurExceptionEventCount,
COALESCE(p.CurPerformanceEventCount, 0) AS CurPerformanceEventCount,
COALESCE(p.LastPerformanceEventCount, 0) AS LastPerformanceEventCount,
COALESCE(p.LastExceptionEventCount, 0) AS LastExceptionEventCount,
COALESCE(p.CurPerformanceProblemCount, 0) AS CurPerformanceProblemCount,
COALESCE(p.CurExceptionProblemCount, 0) AS CurExceptionProblemCount,
COALESCE(p.LastPerformanceProblemCount, 0) AS LastPerformanceProblemCount,
COALESCE(p.LastExceptionProblemCount, 0) AS LastExceptionProblemCount,
COALESCE(p.NewPerfProblemsCount, 0) AS NewPerfProblemsCount,
COALESCE(p.NewExpProblemsCount, 0) AS NewExpProblemsCount
FROM
#SOURCEMACHINEFILTERTABLE AS sd
JOIN APM.Source AS s (NOLOCK) ON sd.VALUEID = s.SourceId
LEFT OUTER JOIN PCounters AS pc ON s.SourceId = pc.Sourceid
LEFT OUTER JOIN Events AS e ON s.Sourceid = e.Sourceid
LEFT OUTER JOIN EventProblems AS p ON s.Sourceid = p.Sourceid
WHERE
sd.TYPEID = 1
)
SELECT
LastResults.Id AS RowId,
SourceId,
Source,
-------Instance Count----------
CurInstanceCount,
LastInstanceCount,
AvgInstanceCount,
-------MonitoredRequest--------
CurMonitoredRequestSum,
LastMonitoredRequestSum,
AvgMonitoredRequestSum,
-------Avg value----------
CurAvrValue,
LastAvgValue,
AvgValue,
------CPU Value----------
CurCPUValue,
LastCPUValue,
CPUAvgValue,
------ Mem value------------
CurMemValue,
LastMemValue,
MemAvgValue,
--------- IO value-------------
CurIOValue,
LastIOValue,
IOAvgValue,
------- Events count----------
AvgEventsCount,
CurrentEventCount,
LastEventCount,
--------- Exception &amp; Performance Event Count ---------
CurExceptionEventCount,
CurPerformanceEventCount,
LastPerformanceEventCount,
LastExceptionEventCount,
-------- Exception &amp; Performance Problem Count ---------
CurPerformanceProblemCount,
CurExceptionProblemCount,
LastPerformanceProblemCount,
LastExceptionProblemCount,
NewPerfProblemsCount,
NewExpProblemsCount
FROM
ResultQuery AS LastResults
ORDER BY
RowId
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.ApplicationStatusDrillthrough'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.ApplicationStatusDrillthrough AS RETURN 1')
END
GO

/****************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: ApplicationStatusDrillthrough */
/* USED IN: Application Status Report, Application Daily Activity */
/* INPUT PARAMETERS: */
/* @SOURCEIDS - List of the source id, separated by comma. Exp: '1,2,3' */
/* @COMPUTERIDS - List of the computer id, separated by comma. Exp: '1,2,3' */
/* @ENDDATE - End date of the period */
/* @PERIOD - Period type(Day, Week or Month). */
/* - Use for the Start Date calculate of the period */
/* @AVERAGEINTERVAL- This value specifies interval, for which average values will */
/* be calculated. Possible values: 1(1 month), 2(2 month), */
/* 3(3 month), 6(6 month), 17 (7 day) */
/* @GROUPBY - Specifies result gouping type. Possible values: */
/* Hour - Group by hours. Rersult set will contain 24 rows */
/* corresponding to 24 hours. Date field - 0-23, Hour field - 0 */
/* WeekDay - Group by week days. For this grouping type extra grouping */
/* is applied - by hours. So result data set contains 7*24 rows. */
/* Date field values - 1-7, Hour fields - 0-23 */
/* Month - Group by Month. For this grouping type extra grouping */
/* is applied - by months. So result data set contains 12*24 rows. */
/* and Hour field - 0-23 */
/* @TRESHOLD - Event duration treshold */
/* @PROBLEM - Event problem type (all, critical) */
/* @TIMEZONE - correlate parameter (timezone by min) */
/* - for the End Date calculate */
/****************************************************************************************/
alter PROCEDURE APM.ApplicationStatusDrillthrough
@SOURCEIDS NVARCHAR(MAX),
@COMPUTERIDS NVARCHAR(MAX),
@ENDDATE DATETIME,
@TIMEZONE INT,
@PERIOD INT,
@AVERAGEINTERVAL INT,
@GROUPBY NVARCHAR(10),
@THRESHOLD INT,
@PROBLEM NVARCHAR(10),
@PMSTATUS NVARCHAR(50)
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON;

/************************************************************************************/
/* Prepare auxiliary variables for the further calculation */
/************************************************************************************/

SET @ENDDATE = DATEADD(minute, -@TIMEZONE, @ENDDATE)

DECLARE @STARTDATE DateTime
SET @STARTDATE = DATEADD(d, -(CASE WHEN @PERIOD = 1 THEN 1 WHEN @PERIOD = 2 THEN 7 ELSE 31 END), @ENDDATE)

DECLARE @LASTPERIODSTARTDATE DateTime
SET @LASTPERIODSTARTDATE = DATEADD(d, -APM.GetQueryDateCount(@PERIOD, @STARTDATE), @STARTDATE)

DECLARE @AVERAGEPERIODSTARTDATE DateTime
SET @AVERAGEPERIODSTARTDATE = (CASE
WHEN @AVERAGEINTERVAL &lt; 10 THEN DATEADD(month, -@AVERAGEINTERVAL, @STARTDATE)
ELSE DATEADD(day, -(@AVERAGEINTERVAL-10), @STARTDATE)
END)

--Used for counting average value for last three months
DECLARE @PERIODDAYSCOUNT int
SET @PERIODDAYSCOUNT = APM.GetQueryDateCount(@PERIOD, @STARTDATE);

DECLARE @PROCESSORCOUNTERID INT
SELECT @PROCESSORCOUNTERID = PCtypeId FROM apm.PCType (NOLOCK) WHERE TYPE = N'\Process\% Processor Time'

DECLARE @MEMORYCOUNTERID INT
SELECT @MEMORYCOUNTERID = PCtypeId FROM apm.PCType (NOLOCK) WHERE TYPE = N'\Process\Private Bytes'

DECLARE @IOCOUNTERID INT
SELECT @IOCOUNTERID = PCtypeId FROM apm.PCType (NOLOCK) WHERE TYPE = N'\Process\IO Data Bytes/sec'

DECLARE @MONITOREDREQUESTCOUNTERID INT
SELECT @MONITOREDREQUESTCOUNTERID = PCtypeId FROM apm.PCType (NOLOCK) WHERE TYPE = N'\Apps\Monitored Requests'

DECLARE @REQUESTTIMECOUNTERID INT
SELECT @REQUESTTIMECOUNTERID = PCtypeId FROM apm.PCType (NOLOCK) WHERE TYPE = N'\Apps\Avg. Request Time'
/************************************************************************************/
/* ASSISTING TEMP TABLES */
/************************************************************************************/
-- Filter table, which contains machine ids and source ids
-- typeid defines filter type - 1 for source and 2 for machine
-- valueId filter value - source id and machine id
CREATE TABLE #SOURCEMACHINEFILTERTABLE(
TYPEID INT,
VALUEID INT
)

-- Fill table #SOURCEMACHINEFILTERTABLE
INSERT
INTO #SOURCEMACHINEFILTERTABLE
SELECT
p.typeId AS TYPEID,
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@SOURCEIDS, @COMPUTERIDS) AS p

-- Filter table, which contains PM Statuses of Events
CREATE TABLE #PMSTATUSFILTERTABLE(
VALUEID INT
)

-- Fill table #PMSTATUSFILTERTABLE
INSERT
INTO #PMSTATUSFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@PMSTATUS, N'') AS p

-- To form application pool with all sources run in it, it is need to get all sources and its process
CREATE TABLE #PROCESSFORSOURCE
(
SOURCEID INT,
PCPROCESSID INT,
MACHINEID INT,
EXTRAINFO NVARCHAR(255) collate database_default,
PROCESS NVARCHAR(255) collate database_default
)

INSERT INTO #PROCESSFORSOURCE
SELECT
ph.SOURCEID,
ph.PCPROCESSID,
ph.MACHINEID,
COALESCE(p.EXTRAINFO, N'') AS EXTRAINFO,
--Select process name till # symbol (w3wp#1 -&gt; w3wp, w3wp -&gt; w3wp)
APM.RemoveProcessIdFromName(p.PROCESS) AS Process
FROM
(
SELECT DISTINCT
ph.SOURCEID,
ph.PCPROCESSID,
ph.MACHINEID
FROM
APM.PerfHourly AS ph (NOLOCK)
WHERE
ph.PCPROCESSID IS NOT NULL
AND ph.UTCDATE &gt;= @STARTDATE
AND ph.UTCDATE &lt; @ENDDATE
) AS ph
JOIN APM.PCProcess AS p (NOLOCK) ON p.PCPROCESSID = ph.PCPROCESSID
JOIN #SOURCEMACHINEFILTERTABLE AS f ON (f.TYPEID = 2 AND ph.MACHINEID = f.VALUEID)



/************************************************************************************/
/* Main query */
/************************************************************************************/

-- Report frame. It contains all sources, for which data sould be selected,
-- and date values accordingly to specified period and grouping type.
;WITH SourcesDates AS
(
SELECT
VALUEID AS sourceid,
s.SOURCE AS source,
Hours.n-1 AS hours,
D.date AS date
FROM
#SOURCEMACHINEFILTERTABLE AS source
JOIN APM.source (NOLOCK) AS s ON s.SOURCEID = source.VALUEID,
APM.fn_nums(
(CASE
WHEN @GROUPBY = 'WeekDay' THEN 24
ELSE 1
END)) AS Hours,
(SELECT
(CASE
WHEN @GROUPBY = 'Hour' THEN n-1
WHEN @GROUPBY = 'WeekDay' THEN n
WHEN @GROUPBY = 'MonthDay' THEN n
END) AS date
FROM
APM.fn_nums(
CASE
WHEN @GROUPBY = 'Hour' THEN 24
WHEN @GROUPBY = 'WeekDay' THEN 7
WHEN @GROUPBY = 'MonthDay' THEN 31
END
)
) AS D
WHERE
source.TYPEID = 1
),
-- Get sources name, ids list separated by comma per app pool
-- This info should be selected for all sources, even they are in the same application pool
-- as in this report grouping by source is applied not by application pool.
AppPoolInfo AS
(
SELECT
c.SOURCEID,
c.EXTRAINFO,
c.PROCESS,
-- all source names which have the same process name as passed in @SOURCEIDS
(SELECT A.source AS [data()]
FROM
(
SELECT DISTINCT
N'''' + s.source + N'''' + N',' AS source
FROM
#PROCESSFORSOURCE AS c1
JOIN APM.Source AS s ON c1.SOURCEID = s.SourceId
WHERE
c1.EXTRAINFO = c.EXTRAINFO
AND c1.PROCESS = c.PROCESS
AND c1.MACHINEID = c.MACHINEID
) AS A
FOR XML PATH ('')
) AS AppPoolSources
FROM
#PROCESSFORSOURCE AS c
JOIN #SOURCEMACHINEFILTERTABLE AS f ON (f.TYPEID = 1 AND f.VALUEID = c.SOURCEID)
GROUP BY
c.SOURCEID,
c.MACHINEID,
c.EXTRAINFO,
c.PROCESS
),
--Add Pool name in-front of source list, if it is executable application, then app pool countains source name
PrepareAppPoolInfo AS (
SELECT DISTINCT
CASE
WHEN COALESCE(info.EXTRAINFO,'') = '' THEN CASE info.AppPoolSources WHEN '' THEN '' ELSE LEFT(info.AppPoolSources, LEN(info.AppPoolSources)-1) END
ELSE info.EXTRAINFO + CASE info.AppPoolSources WHEN '' THEN '' ELSE ' (' + LEFT(info.AppPoolSources, LEN(info.AppPoolSources) - 1) + ')' END
END AppPool,
info.SOURCEID,
info.EXTRAINFO
FROM
AppPoolInfo AS info
),
-- Forms application pool list for each source
-- Format: AppPool1 ('Source1', 'Source2', Source3), AppPool2 ('Source1', 'Source4')
SourceAppPools AS (
SELECT
s.SOURCEID,
s.SOURCE,
COALESCE((SELECT a.AppPool AS [data()]
FROM
(
SELECT DISTINCT
info.AppPool + N',' AS AppPool
FROM
PrepareAppPoolInfo as info
WHERE
info.Sourceid = s.Sourceid
) AS A
FOR XML PATH ('')
),s.SOURCE + '-') AS AppPoolInfo
FROM
APM.Source AS s
JOIN #SOURCEMACHINEFILTERTABLE AS f ON (f.TYPEID = 1 AND f.VALUEID = s.SOURCEID)
),
--Prepares and filters events for further manipulations
ActivityBreakdown_EventsFiltered AS
(
SELECT
e.SOURCEID,
e.EVENTID,
e.UTCEVENTDATE AS eventdate,
--Removing APM.GetDatePart replacing the execution by the code below.
--It boosts the overall performance as it reduces the number of calls of scalar function
CASE @GROUPBY
WHEN 'Hour' THEN Datepart(hh, DATEADD(mi, CAST(@TIMEZONE AS int), e.utceventdate))
WHEN 'WeekDay' THEN Datepart(dw, DATEADD(mi, CAST(@TIMEZONE AS int), e.utceventdate))
WHEN 'MonthDay' THEN Datepart(d, DATEADD(mi, CAST(@TIMEZONE AS int), e.utceventdate))
END as date,
CASE
WHEN @GROUPBY = 'WeekDay'
THEN DatePart(Hour, DATEADD(mi, CAST(@TIMEZONE AS int), e.utceventdate))
ELSE 0
END AS Hour,
--hour is taken as DateDifference in day between 05/04/2009 9:00AM and 05/03/2009 9:00PM is one day,
--despite in case of @PERIOD = 'Day' it can be interpretated as one day (if 05/04/2009 9:00AM is end date), so difference should be taken as 0
ABS(DATEDIFF(hour, e.UTCEVENTDATE, @STARTDATE)) / (@PERIODDAYSCOUNT*24) AS PeriodId,
e.EVENTGROUPID,
db.ADDRESS AS SeViewerAddress
FROM
APM.Event AS e
JOIN APM.SeViewerDB AS db ON e.SEVIEWERDBID = db.SEVIEWERDBID
JOIN #SOURCEMACHINEFILTERTABLE AS f1 ON (f1.VALUEID = e.SOURCEID and f1.TYPEID = 1)
JOIN #SOURCEMACHINEFILTERTABLE AS f2 ON (f2.VALUEID = e.MACHINEID and f2.TYPEID = 2)
JOIN #PMSTATUSFILTERTABLE AS f3 ON (f3.VALUEID = e.PMSTATUS)
WHERE
((e.EVENTCLASSTYPE = N'Performance' AND e.EVENTDURATION / 1000000.0 &gt;= @THRESHOLD)
OR e.EVENTCLASSTYPE = N'exception')
AND (e.CATEGORY LIKE @PROBLEM OR e.CATEGORY IS NULL)
AND e.UTCEVENTDATE &gt;= @AVERAGEPERIODSTARTDATE
AND e.UTCEVENTDATE &lt; @ENDDATE
AND (e.HEAVYLIGHT &lt;&gt; 0 OR e.HeavyLight IS NULL)

),
/************************************************************************************/
/* Base pcounter queries */
/************************************************************************************/
-- Calculate resource utilization by Source in one hour.
-- Aggregation between instances should be done here (for cases when one source run in several process in one hour)
SourceHourlyResourceUtilization AS
(
SELECT
ph.MACHINEID,
ph.SOURCEID,
ph.UTCDATE,
ph.PCTYPEID AS Type,

---------- Pivot instance count by period type -----------
(CASE
WHEN ph.UTCDATE &gt;= @LASTPERIODSTARTDATE AND ph.UTCDATE &lt; @STARTDATE
THEN SUM(ph.SAMPLECOUNT)*1.0/MAX(ph.PACKAGECOUNTER)
END) AS LastInstanceCount,
(CASE
WHEN ph.UTCDATE &gt;= @STARTDATE AND ph.UTCDATE &lt; @ENDDATE
THEN SUM(ph.SAMPLECOUNT)*1.0/MAX(ph.PACKAGECOUNTER)
END) AS CurInstanceCount,
(CASE
WHEN ph.UTCDATE &gt;= @AVERAGEPERIODSTARTDATE AND ph.UTCDATE &lt; @STARTDATE
THEN SUM(ph.SAMPLECOUNT)*1.0/MAX(ph.PACKAGECOUNTER)
END) AS AvgInstanceCount,

---------- Pivot resource value by period type -----------
(CASE
WHEN ph.UTCDATE &gt;= @LASTPERIODSTARTDATE AND ph.UTCDATE &lt; @STARTDATE THEN SUM(SumValue)/SUM(SampleCount)
END) AS LastValue,
(CASE
WHEN ph.UTCDATE &gt;= @STARTDATE AND ph.UTCDATE &lt; @ENDDATE THEN SUM(SumValue)/SUM(SampleCount)
END) AS CurValue,
(CASE
WHEN ph.UTCDATE &gt;= @AVERAGEPERIODSTARTDATE AND ph.UTCDATE &lt; @STARTDATE THEN SUM(SumValue)/SUM(SampleCount)
END) AS AvgValue,
--Removing APM.GetDatePart replacing the execution by the code below.
--It boosts the overall performance as it reduces the number of calls of scalar function
CASE @GROUPBY
WHEN 'Hour' THEN Datepart(hh, DATEADD(mi, CAST(@TIMEZONE AS int), ph.UTCDate))
WHEN 'WeekDay' THEN Datepart(dw, DATEADD(mi, CAST(@TIMEZONE AS int), ph.UTCDate))
WHEN 'MonthDay' THEN Datepart(d, DATEADD(mi, CAST(@TIMEZONE AS int), ph.UTCDate))
END as Date,
(CASE WHEN @GROUPBY = 'WeekDay' THEN DatePart(Hour, DATEADD(mi, CAST(@TIMEZONE AS int), ph.UTCDate)) ELSE 0 END) AS Hours,
--hour is taken as DateDifference in day between 05/04/2009 9:00AM and 05/03/2009 9:00PM is one day,
--despite in case of @PERIOD = 'Day' it can be interpretated as one day (if 05/04/2009 9:00AM is end date), so difference should be taken as 0
ABS(DATEDIFF(hour, ph.UTCDATE, @ENDDATE)) / (@PERIODDAYSCOUNT*24) AS PeriodId
FROM
APM.PerfHourly AS ph (NOLOCK)
--Join with #SOURCEMACHINEFILTERTABLE with typeid = 1 provides filtering perfHourly by sourceid
JOIN #SOURCEMACHINEFILTERTABLE AS f1 ON (f1.TYPEID = 1 AND f1.VALUEID = ph.SOURCEID)
--Join with #SOURCEMACHINEFILTERTABLE with typeid = 2 provides filtering perfHourly by machineid
JOIN #SOURCEMACHINEFILTERTABLE AS f2 ON (f2.TYPEID = 2 AND f2.VALUEID = ph.MACHINEID)
WHERE
ph.UTCDATE &gt;= @AVERAGEPERIODSTARTDATE
AND ph.UTCDATE &lt; @ENDDATE
AND ph.PCTYPEID IN (@PROCESSORCOUNTERID, @IOCOUNTERID, @MEMORYCOUNTERID)
GROUP BY
ph.MACHINEID,
ph.SOURCEID,
ph.UTCDATE,
ph.PCTYPEID
)
,
--Calculate average source resource utilization for each resource type
--and for specified grouping period and date
ApplicationResourceUtilizationByMachines AS
(
SELECT
ph.MachineId,
ph.SourceId,
ph.PeriodId,
ph.Date,
ph.Hours,
-- Instance count should be same for different resource types in one hour for one process
-- and averaging them won't make any difference but allow to avoid one aggregation step
AVG(ph.CurInstanceCount) AS CurInstanceCount,
AVG(ph.LastInstanceCount) AS LastInstanceCount,
AVG(ph.AvgInstanceCount) AS AvgInstanceCount,

---------- Pivot resource by counter type -----------

----------- 'Process% Processor Time' counter -------------------
AVG(CASE WHEN ph.type = @PROCESSORCOUNTERID THEN ph.CurValue END) AS CurCPUSum,
AVG(CASE WHEN ph.type = @PROCESSORCOUNTERID THEN ph.LastValue END) AS LastCPUSum,
AVG(CASE WHEN ph.type = @PROCESSORCOUNTERID THEN ph.AvgValue END) AS AvgCPUSum,

----------- 'ProcessPrivate Bytes' counter -------------------
AVG(CASE WHEN ph.type = @MEMORYCOUNTERID THEN ph.CurValue END) AS CurMemSum,
AVG(CASE WHEN ph.type = @MEMORYCOUNTERID THEN ph.LastValue END) AS LastMemSum,
AVG(CASE WHEN ph.type = @MEMORYCOUNTERID THEN ph.AvgValue END) AS AvgMemSum,

----------- 'ProcessIO Data Bytes/sec' counter -------------------
AVG(CASE WHEN ph.type = @IOCOUNTERID THEN ph.CurValue END) AS CurIOSum,
AVG(CASE WHEN ph.type = @IOCOUNTERID THEN ph.LastValue END) AS LastIOSum,
AVG(CASE WHEN ph.type = @IOCOUNTERID THEN ph.AvgValue END) AS AvgIOSum
FROM
SourceHourlyResourceUtilization AS ph
GROUP BY
ph.MachineId,
ph.SourceId,
ph.PeriodId,
ph.Date,
ph.Hours
),
-- Count Monitored Requests and Avg. Request Time for Application on each machine
-- as source can run on different machines with same process name and app pool, but different sources set,
-- it is important to group by machine to, to avoid calculation of requests from the other app pool
-- Summarize request count in each period (PeriodId differs only for AvgValue)
ApplicationNetAppCountersByMachinePrepare AS
(
SELECT
ph.MACHINEID,
ph.SOURCEID,
----------------- Pivot Monitor Request Counter by period ------------------
CASE WHEN ph.UTCDATE &gt;= @LASTPERIODSTARTDATE AND ph.UTCDATE &lt; @STARTDATE
THEN SUM(CASE WHEN ph.PCTYPEID = @MONITOREDREQUESTCOUNTERID THEN ph.SUMVALUE END)
END AS LastMonRequest,
CASE WHEN ph.UTCDATE &gt;= @STARTDATE AND ph.UTCDATE &lt; @ENDDATE
THEN SUM(CASE WHEN ph.PCTYPEID = @MONITOREDREQUESTCOUNTERID THEN ph.SUMVALUE END)
END AS CurMonRequest,
CASE WHEN ph.UTCDATE &gt;= @AVERAGEPERIODSTARTDATE AND ph.UTCDATE &lt; @STARTDATE
THEN SUM(CASE WHEN ph.PCTYPEID = @MONITOREDREQUESTCOUNTERID THEN ph.SUMVALUE END)
END AS AvgMonRequest,

----------------- Pivot Avg. Request Time Counter by period ------------------
CASE WHEN ph.UTCDATE &gt;= @LASTPERIODSTARTDATE AND ph.UTCDATE &lt; @STARTDATE
THEN AVG(CASE WHEN ph.PCTYPEID = @REQUESTTIMECOUNTERID THEN ph.SUMVALUE / ph.SAMPLECOUNT END)
END AS LastAvgReqTime,
CASE WHEN ph.UTCDATE &gt;= @STARTDATE AND ph.UTCDATE &lt; @ENDDATE
THEN AVG(CASE WHEN ph.PCTYPEID = @REQUESTTIMECOUNTERID THEN ph.SUMVALUE / ph.SAMPLECOUNT END)
END AS CurAvgReqTime,
CASE WHEN ph.utcdate &gt;= @AVERAGEPERIODSTARTDATE AND ph.utcdate &lt; @STARTDATE
THEN AVG(CASE WHEN ph.PCTYPEID = @REQUESTTIMECOUNTERID THEN ph.SUMVALUE / ph.SAMPLECOUNT END)
END AS AvgReqTime,
--Removing APM.GetDatePart replacing the execution by the code below.
--It boosts the overall performance as it reduces the number of calls of scalar function
CASE @GROUPBY
WHEN 'Hour' THEN Datepart(hh, DATEADD(mi, CAST(@TIMEZONE AS int), ph.UTCDATE))
WHEN 'WeekDay' THEN Datepart(dw, DATEADD(mi, CAST(@TIMEZONE AS int), ph.UTCDATE))
WHEN 'MonthDay' THEN Datepart(d, DATEADD(mi, CAST(@TIMEZONE AS int), ph.UTCDATE))
END as Date,
(CASE WHEN @GROUPBY = 'WeekDay' THEN DatePart(Hour, DATEADD(mi, CAST(@TIMEZONE AS int), ph.UTCDATE)) ELSE 0 END) AS Hours,
--hour is taken as DateDifference in day between 05/04/2009 9:00AM and 05/03/2009 9:00PM is one day,
--despite in case of @PERIOD = 'Day' it can be interpretated as one day (if 05/04/2009 9:00AM is end date), so difference should be taken as 0
ABS(DATEDIFF(hour, ph.UTCDATE, @ENDDATE)) / (@PERIODDAYSCOUNT*24) AS PeriodId
FROM
APM.PerfHourly AS ph (NOLOCK)
--Join with #SOURCEMACHINEFILTERTABLE provides filtering perfHourly by sourceid
JOIN #SOURCEMACHINEFILTERTABLE AS f1 ON (f1.TYPEID = 1 AND ph.SOURCEID = f1.VALUEID)
--Join with #SOURCEMACHINEFILTERTABLE provides filtering perfHourly by machineid
JOIN #SOURCEMACHINEFILTERTABLE AS f2 ON (f2.TYPEID = 2 AND f2.VALUEID = ph.MACHINEID)
WHERE
ph.UTCDATE &gt;= @AVERAGEPERIODSTARTDATE
AND ph.UTCDATE &lt; @ENDDATE
AND ph.PCTYPEID IN (@REQUESTTIMECOUNTERID, @MONITOREDREQUESTCOUNTERID)
GROUP BY
ph.MACHINEID,
ph.SOURCEID,
ph.UTCDATE
),
--Calculate average request time and sum request count for specified grouping period and date
ApplicationNetAppCountersByMachine AS
(
SELECT
ph.MachineId,
ph.SourceId,
ph.PeriodId,
ph.Date,
ph.Hours,
SUM(ph.LastMonRequest) AS LastMonRequest,
SUM(ph.CurMonRequest) AS CurMonRequest,
SUM(ph.AvgMonRequest) AS AvgMonRequest,
AVG(ph.LastAvgReqTime) AS LastAvgReqTime,
AVG(ph.CurAvgReqTime) AS CurAvgReqTime,
AVG(ph.AvgReqTime) AS AvgReqTime
FROM
ApplicationNetAppCountersByMachinePrepare ph
GROUP BY
ph.MachineId,
ph.SourceId,
ph.PeriodId,
ph.Date,
ph.Hours
),
-- Union .NET counters and process counters for period Id. Period Id differs only for average(last three months) values, so grouping only for them
PCountersGroupedByMachineId AS (
SELECT
pc.machineId,
pc.SourceId,
pc.Hours,
pc.date,

MAX(netApp.CurMonRequest) AS CurReqCount,
MAX(netApp.LastMonRequest) AS LastReqCount,
AVG(netApp.AvgMonRequest) AS AvgReqCount,

MAX(netApp.CurAvgReqTime) AS CurAvgReqTime,
MAX(netApp.LastAvgReqTime) AS LastAvgReqTime,
AVG(netApp.AvgReqTime) AS AvgReqTime,

MAX(pc.CurCPUSum) AS CurCPUSum,
MAX(pc.LastCPUSum) AS LastCPUSum,
AVG(pc.AvgCPUSum) AS AvgCPUSum,
MAX(pc.CurMemSum) AS CurMemSum,
MAX(pc.LastMemSum) AS LastMemSum,
AVG(pc.AvgMemSum) AS AvgMemSum,
MAX(pc.CurIOSum) AS CurIOSum,
MAX(pc.LastIOSum) AS LastIOSum,
AVG(pc.AvgIOSum) AS AvgIOSum
FROM ApplicationResourceUtilizationByMachines pc
LEFT JOIN ApplicationNetAppCountersByMachine AS netApp ON netApp.MachineId = pc.MachineId
AND netApp.SourceId = pc.SourceId AND netApp.PeriodId = netApp.PeriodId
AND netApp.Hours = pc.Hours AND netApp.Date = pc.Date
GROUP BY
pc.machineId,
pc.SourceId,
pc.Hours,
pc.date
),
-- Calculate average source resource utilization between machines
ActivePreparePCounters AS (
SELECT
pc.SourceId,
pc.Hours,
pc.date,
SUM(CurReqCount) AS CurReqCount,
SUM(LastReqCount) AS LastReqCount,
SUM(AvgReqCount) AS AvgReqCount,
AVG(CurAvgReqTime) AS CurAvgReqTime,
AVG(LastAvgReqTime) AS LastAvgReqTime,
AVG(AvgReqTime) AS AvgReqTime,
AVG(CurCPUSum / COALESCE(m.CPUCount, 1)) AS CurCPUSum,
AVG(LastCPUSum / COALESCE(m.CPUCount, 1) ) AS LastCPUSum,
AVG(AvgCPUSum / COALESCE(m.CPUCount, 1)) AS AvgCPUSum,


AVG(CurMemSum) AS CurMemSum,
AVG(LastMemSum) AS LastMemSum,
AVG(AvgMemSum) AS AvgMemSum,
AVG(CurIOSum) AS CurIOSum,
AVG(LastIOSum) AS LastIOSum,
AVG(AvgIOSum) AS AvgIOSum
FROM
PCountersGroupedByMachineId pc
JOIN APM.Machine AS m ON m.MACHINEID = pc.MachineId
GROUP BY
pc.SourceId,
pc.Hours,
pc.date
),
--Count events for the current, last and average period. PeriodId differs only for average
PrepareEventsAvg AS
(
SELECT
e.sourceid AS sourceid,
e.date,
e.hour,
e.PeriodId,
MAX(E.SeViewerAddress) AS SeViewerAddress,
COUNT(CASE WHEN e.eventdate &gt;= @STARTDATE AND e.eventdate &lt; @ENDDATE THEN eventid END) AS CurrentEventsCount,
COUNT(CASE WHEN e.eventdate &gt;= @LASTPERIODSTARTDATE AND e.eventdate &lt; @STARTDATE THEN eventid END) AS LasEventsCount,
COUNT(CASE WHEN E.eventdate &gt;= @AVERAGEPERIODSTARTDATE AND E.eventdate &lt; @STARTDATE THEN eventid END) AS AvgEventsCount
FROM
ActivityBreakdown_EventsFiltered AS e
GROUP BY
sourceid,
PeriodId,
e.date,
e.hour
),
Events AS
(
SELECT
e.sourceid AS sourceid,
e.date,
e.hour,
MAX(E.SeViewerAddress) AS SeViewerAddress,
--PeriodId differs only for average, so for current and last period it doesn't matter which agg function is taken
MAX(CurrentEventsCount) AS CurrentEventsCount,
MAX(LasEventsCount) AS LasEventsCount,
--Average counting is not included current period
AVG(AvgEventsCount) AS AvgEventsCount
FROM
PrepareEventsAvg AS e
GROUP BY
sourceid,
e.date,
e.hour
),
MachineCPUUndefinedFlag AS
(
SELECT
sf.SOURCEID,
MIN(COALESCE(m.CPUCOUNT, -1)) AS CPUUndefinedFlag
FROM
#PROCESSFORSOURCE AS sf
JOIN APM.Machine AS m (NOLOCK) ON sf.MACHINEID = m.MACHINEID
GROUP BY
sf.SOURCEID
)
SELECT
-- This fake fields is need to provide compatibility with SP ApplicationStatusDrillthrough
GetDate() AS ClientDate,
SourcesDates.date AS Date,
SourcesDates.Hours AS Hours,
SourcesDates.Sourceid,
SourcesDates.Source AS Source,
--Period is used to organize result values, for example if @PERIOD is Day and @ENDDATE = '05/06/2009 13:00',
--this value should put 23 hour of 05/05/2009 before 10 hour of 05/06/2009
(CASE
WHEN (SourcesDates.date - APM.GetDatePart(@GROUPBY, DATEADD(mi, CAST(@TIMEZONE AS int), @ENDDATE))
) &lt; 0 THEN 0
WHEN (SourcesDates.date - APM.GetDatePart(@GROUPBY, DATEADD(mi, CAST(@TIMEZONE AS int), @ENDDATE))
) &gt;= 0 THEN 1
END) AS Period,
COALESCE(pc.CurReqCount, 0) AS CurMonitoredRequestSum,
COALESCE(pc.LastReqCount, 0) AS LastMonitoredRequestSum,
COALESCE(pc.AvgReqCount, 0) AS AvgMonitoredRequestSum,
COALESCE(pc.CurAvgReqTime, 0) AS CurAvgReqTime,
COALESCE(pc.LastAvgReqTime, 0) AS LastAvgReqTime,
COALESCE(pc.AvgReqTime, 0) AS AvgReqTime,
COALESCE(pc.CurCPUSum, 0) AS CurCPUValue,
COALESCE(pc.lastCPUSum, 0) AS LastCPUValue,
COALESCE(pc.AvgCPUSum, 0) AS AvgValue,
COALESCE(pc.CurMemSum, 0) AS CurMemValue,
COALESCE(pc.LastMemSum, 0) AS LastMemValue,
COALESCE(pc.AvgMemSum, 0) AS AvgMemValue,
COALESCE(pc.CurIOSum, 0) AS CurIOValue,
COALESCE(pc.LastIOSum, 0) AS LastIOValue,
COALESCE(pc.AvgIOSum, 0) AS AvgIOValue,
COALESCE(e.CurrentEventsCount, 0) AS NewEventsCount,
COALESCE(e.LasEventsCount, 0) AS OldEventsCount,
COALESCE(e.AvgEventsCount, 0) AS AvgEventsCount,
-- cpuFlag.CPUUndefinedFlag is null for current source if there is no one process PCounter row
-- in PerfHourly table for specified period. If so there is no need to show message about it
COALESCE(cpuFlag.CPUUndefinedFlag, 1) AS CPUUndefinedFlag,
(CASE
WHEN (@GROUPBY = 'Hour' AND ((SourcesDates.date % 2) = 0)) THEN SourcesDates.date
WHEN (@GROUPBY = 'WeekDay' AND ((SourcesDates.Hours + 12) % 24) = 0) THEN SourcesDates.date
WHEN (@GROUPBY = 'MonthDay') THEN SourcesDates.date
ELSE -1
END) AS OutputDate,
CASE LEFT(AppPool.AppPoolInfo,1)
WHEN N'''' THEN N''
WHEN N'' THEN ''
ELSE REPLACE(LEFT(AppPool.AppPoolInfo, LEN(AppPool.AppPoolInfo)-1), N'''', N'')
END AS pool,
E.SeViewerAddress
FROM
SourcesDates
LEFT OUTER JOIN MachineCPUUndefinedFlag AS cpuFlag ON SourcesDates.Sourceid = cpuFlag.Sourceid
LEFT OUTER JOIN ActivePreparePCounters AS pc ON (pc.date = SourcesDates.date AND pc.SourceId = SourcesDates.Sourceid AND SourcesDates.Hours = pc.Hours)
LEFT OUTER JOIN Events AS e ON (e.date = SourcesDates.date AND e.Sourceid = SourcesDates.Sourceid AND e.hour = SourcesDates.Hours)
JOIN SourceAppPools AS AppPool ON (AppPool.Sourceid = SourcesDates.Sourceid)
ORDER BY
Source,
Period DESC,
Date,
Hours
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.Application_sync'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.Application_sync AS RETURN 1')
END
GO

/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: Application_sync */
/* USED IN: Synchronization of SE-Viewer.'Application' table. */
/* Call by Intercept Reporting Services */
/* INPUT PARAMETERS: */
/* @OBJECTKEYXML - xml package syncronization data */
/* @TRACELEVEL - trace level. Reserved. */
/* OUTPUT PARAMETERS: */
/* @ROWNOTAFFECTED - number of records from package which haven't been */
/* synchronized.Reserved. */
/* Note: */
/* If there are records which have not been transferred that they have been already */
/* transferred from other SEVIEWER database earlier. Any other reason will cause a */
/* exception at an insert */
/************************************************************************************/
ALTER PROCEDURE APM.Application_sync
@OBJECTKEYXML ntext,
@TRACELEVEL int,
@ROWNOTAFFECTED int output
AS
BEGIN
SET NOCOUNT ON

DECLARE
@ERRORIND bit
,@ERRORMESSAGE nvarchar(max)
,@ERRORNUMBER int
,@ERRORSEVERITY int
,@ERRORSTATE int
,@ERRORLINE int
,@ERRORPROCEDURE nvarchar(256)
,@ERRORMESSAGETEXT nvarchar(max)

SET @ERRORIND = 0

BEGIN TRY

SET @ROWNOTAFFECTED = 0

DECLARE
@EXECRESULT int
,@XMLDOCHANDLE int
,@ERROR_MESSAGE nvarchar(max)

EXEC @EXECRESULT = sp_xml_preparedocument @XMLDOCHANDLE OUTPUT, @OBJECTKEYXML
IF @EXECRESULT &lt;&gt; 0
BEGIN
SELECT @ERROR_MESSAGE = message FROM APM.messages WHERE id = 50002
RAISERROR(@ERROR_MESSAGE, 16, 1, 'Application_sync', @EXECRESULT)
END

DECLARE @APPLICATION TABLE (
application nvarchar(255) collate database_default NOT NULL
)

----Fill table from package
INSERT @APPLICATION (
application
)
SELECT
application
FROM OPENXML(@XMLDOCHANDLE, 'rows/row', 2) WITH (
application nvarchar(255) ) xml

EXEC sp_xml_removedocument @XMLDOCHANDLE

SET @XMLDOCHANDLE = NULL

--insert not existing applications
INSERT APM.application (application,type)
SELECT DISTINCT sync.application , 3
FROM @APPLICATION sync
WHERE NOT EXISTS (SELECT * FROM APM.application a WHERE (a.application = sync.application))

END TRY
BEGIN CATCH
IF (@@TRANCOUNT &gt; 0)
ROLLBACK TRAN

SELECT
@ERRORNUMBER = ERROR_NUMBER()
,@ERRORSEVERITY = ERROR_SEVERITY()
,@ERRORSTATE = ERROR_STATE()
,@ERRORLINE = ERROR_LINE()
,@ERRORPROCEDURE = ISNULL(ERROR_PROCEDURE(), '-')
,@ERRORMESSAGETEXT = ERROR_MESSAGE()

SET @ERRORIND = 1
END CATCH

IF @XMLDOCHANDLE IS NOT NULL
EXEC sp_xml_removedocument @XMLDOCHANDLE

-- report error if any
IF (@ERRORIND = 1)
BEGIN
DECLARE @ADJUSTEDERRORSEVERITY int

SET @ADJUSTEDERRORSEVERITY = CASE
WHEN @ERRORSEVERITY = 2601 OR @ERRORSEVERITY = 2627 THEN 0
WHEN @ERRORSEVERITY &gt; 18 THEN 18
ELSE @ERRORSEVERITY
END

SELECT @ERROR_MESSAGE = message FROM APM.Messages WHERE id = 50004
RAISERROR (@ERROR_MESSAGE, @ADJUSTEDERRORSEVERITY, 1
,@ERRORNUMBER
,@ERRORSEVERITY
,@ERRORSTATE
,@ERRORPROCEDURE
,@ERRORLINE
,@ERRORMESSAGETEXT
)
END
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.ApplicationSourceMachine_sync'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.ApplicationSourceMachine_sync AS RETURN 1')
END
GO

/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: ApplicationSourceMachine_sync */
/* USED IN: Synchronization of SE_VIEWER:'applicationsourcemachine' table. */
/* Call by Intercept Reporting Services */
/* INPUT PARAMETERS: */
/* @OBJECTKEYXML - xml package syncronization data */
/* @TRACELEVEL - trace level. Reserved. */
/* OUTPUT PARAMETERS: */
/* @ROWNOTAFFECTED - number of records from package which haven't been */
/* synchronized.Reserved. */
/* Note: */
/* If there are records which have not been transferred that they have been already */
/* transferred from other SEVIEWER database earlier. Any other reason will cause a */
/* exception at an insert */
/************************************************************************************/
ALTER PROCEDURE [APM].[ApplicationSourceMachine_sync]
@OBJECTKEYXML ntext,
@TRACELEVEL int,
@ROWNOTAFFECTED int output
AS
BEGIN
SET NOCOUNT ON

DECLARE
@ERRORIND bit
,@ERRORMESSAGE nvarchar(max)
,@ERRORNUMBER int
,@ERRORSEVERITY int
,@ERRORSTATE int
,@ERRORLINE int
,@ERRORPROCEDURE nvarchar(256)
,@ERRORMESSAGETEXT nvarchar(max)

SET @ERRORIND = 0

BEGIN TRY

SET @ROWNOTAFFECTED = 0

DECLARE
@EXECRESULT int
,@XMLDOCHANDLE int
,@ERROR_MESSAGE nvarchar(max)

EXEC @EXECRESULT = sp_xml_preparedocument @XMLDOCHANDLE OUTPUT, @OBJECTKEYXML
IF @EXECRESULT &lt;&gt; 0
BEGIN
SELECT @ERROR_MESSAGE = message FROM APM.messages WHERE id = 50002
RAISERROR(@ERROR_MESSAGE, 16, 1, 'ApplicationSourceMachine_sync', @EXECRESULT)
END

DECLARE @APPLICATIONSOURCEMACHINE TABLE (
application nvarchar(255) collate database_default NOT NULL,
source nvarchar(255) collate database_default ,
machine nvarchar(255) collate database_default
)

----Fill table from package
INSERT @APPLICATIONSOURCEMACHINE(
application,source,machine
)
SELECT
application,source,machinename
FROM OPENXML(@XMLDOCHANDLE, 'rows/row', 2) WITH (
application nvarchar(255),
source nvarchar(255),
machinename nvarchar(255) ) xml

EXEC sp_xml_removedocument @XMLDOCHANDLE

SET @XMLDOCHANDLE = NULL

DECLARE @ALLAPPID int
DECLARE @NEWMACHINES TABLE (machineId int)

----- machine can be removed using "Remove computers wizard" so it is need synchronize machines ----
INSERT APM.MACHINE (MACHINE) OUTPUT INSERTED.MACHINEID INTO @NEWMACHINES
SELECT DISTINCT machine FROM @APPLICATIONSOURCEMACHINE app
WHERE NOT EXISTS (SELECT * FROM APM.machine m (NOLOCK) WHERE m.machine = app.machine) AND app.machine IS NOT NULL

IF EXISTS(SELECT * FROM @NEWMACHINES)
BEGIN
IF @ALLAPPID IS NULL
SELECT @ALLAPPID = APPLICATIONID FROM APM.APPLICATION (NOLOCK) WHERE APPLICATION = N'All'
---- it is need to create the links with 'All' application group for new sources
INSERT APM.APPLICATIONSOURCEMACHINE
( APPLICATIONID ,
SOURCEID ,
MACHINEID
)
SELECT
@ALLAPPID
,s.SourceId
,m.machineId
FROM
APM.SOURCE (NOLOCK) AS s
CROSS JOIN @NEWMACHINES as m
WHERE
NOT EXISTS
(
SELECT * FROM APM.APPLICATIONSOURCEMACHINE (NOLOCK) AS a
WHERE a.SOURCEID = s.sourceId AND a.APPLICATIONID = @ALLAPPID AND m.machineId = a.machineid
)
END

----- sources can be removed using "Remove applications wizard" so it is need synchronize sources ----
DECLARE @NEWSOURCES TABLE (sourceid int)

----- sources can be removed using "Remove applications wizard" so it is need synchronize sources ----
INSERT APM.SOURCE (SOURCE) OUTPUT INSERTED.SOURCEID INTO @NEWSOURCES
SELECT DISTINCT source FROM @APPLICATIONSOURCEMACHINE app
WHERE NOT EXISTS (SELECT * FROM APM.source s (NOLOCK) WHERE s.source = app.source) AND app.source IS NOT NULL

IF EXISTS(SELECT * FROM @NEWSOURCES)
BEGIN
IF @ALLAPPID IS NULL
SELECT @ALLAPPID = APPLICATIONID FROM APM.APPLICATION (NOLOCK) WHERE APPLICATION = N'All'
---- it is need to create the links with 'All' application group for new machines
INSERT APM.APPLICATIONSOURCEMACHINE
( APPLICATIONID ,
SOURCEID ,
MACHINEID
)
SELECT
@ALLAPPID
,s.sourceid
,m.machineId
FROM
APM.MACHINE (NOLOCK) AS m
CROSS JOIN @NEWSOURCES as s
WHERE
NOT EXISTS
(
SELECT * FROM APM.APPLICATIONSOURCEMACHINE (NOLOCK) AS a
WHERE a.SOURCEID = s.sourceid AND a.APPLICATIONID = @ALLAPPID AND m.MACHINEid = a.machineid
)
END

--insert not existing rows
--don't transfers rows with source is not found or machine is not found
INSERT APM.applicationsourcemachine (applicationid,sourceid,machineid)
SELECT DISTINCT a.applicationid,s.sourceid,m.machineid
FROM @APPLICATIONSOURCEMACHINE sync
JOIN APM.Application a ON a.application = sync.application
JOIN APM.Source s ON s.source = sync.source
JOIN APM.Machine m ON m.machine = sync.machine
WHERE NOT EXISTS ( SELECT * FROM APM.applicationsourcemachine asm
WHERE ( asm.applicationid = a.applicationid AND
asm.sourceid = s.sourceid AND
asm.machineid = m.machineid
))

END TRY
BEGIN CATCH
IF (@@TRANCOUNT &gt; 0)
ROLLBACK TRAN

SELECT
@ERRORNUMBER = ERROR_NUMBER()
,@ERRORSEVERITY = ERROR_SEVERITY()
,@ERRORSTATE = ERROR_STATE()
,@ERRORLINE = ERROR_LINE()
,@ERRORPROCEDURE = ISNULL(ERROR_PROCEDURE(), '-')
,@ERRORMESSAGETEXT = ERROR_MESSAGE()

SET @ERRORIND = 1
END CATCH

IF @XMLDOCHANDLE IS NOT NULL
EXEC sp_xml_removedocument @XMLDOCHANDLE

-- report error if any
IF (@ERRORIND = 1)
BEGIN
DECLARE @ADJUSTEDERRORSEVERITY int

SET @ADJUSTEDERRORSEVERITY = CASE
WHEN @ERRORSEVERITY = 2601 OR @ERRORSEVERITY = 2627 THEN 0
WHEN @ERRORSEVERITY &gt; 18 THEN 18
ELSE @ERRORSEVERITY
END

SELECT @ERROR_MESSAGE = message FROM APM.Messages WHERE id = 50004
RAISERROR (@ERROR_MESSAGE, @ADJUSTEDERRORSEVERITY, 1
,@ERRORNUMBER
,@ERRORSEVERITY
,@ERRORSTATE
,@ERRORPROCEDURE
,@ERRORLINE
,@ERRORMESSAGETEXT
)
END
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.SummaryQualityAnalysis'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.SummaryQualityAnalysis AS RETURN 1')
END
GO

/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: SummaryQualityAnalysis */
/* USED IN: SummaryQualityAnalysisSubReport.rdl */
/* INPUT PARAMETERS: */
/* @SOURCEID - Source id */
/* @COMPUTERIDS - List of the computer id, separated by comma. Exp: '1,2,3' */
/* @STARTDATE - Start date of the period */
/* @ENDDATE - End date of the period */
/* @TRESHOLD - Event duration treshold */
/* @PROBLEM - Event problem type (all, critical) */
/************************************************************************************/
ALTER PROCEDURE [APM].[SummaryQualityAnalysis]
@SOURCEID NVARCHAR(255),
@COMPUTERIDS NVARCHAR(MAX),
@STARTDATE DATETIME,
@ENDDATE DATETIME,
@THRESHOLD INT,
@PROBLEM NVARCHAR(10),
@PMSTATUS NVARCHAR(50) WITH RECOMPILE
AS
BEGIN
/************************************************************************************/
/* ASSISTING TEMP TABLES */
/************************************************************************************/



-- Filter table, which contains machine ids and source ids
-- typeid defines filter type - 1 for source and 2 for machine
-- valueId filter value - source id and machine id
CREATE TABLE #SOURCEMACHINEFILTERTABLE(
TYPEID INT,
VALUEID INT
)

-- Fill table #SOURCEMACHINEFILTERTABLE
INSERT
INTO #SOURCEMACHINEFILTERTABLE
SELECT
p.typeId AS TYPEID,
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@SOURCEID, @COMPUTERIDS) AS p

-- Filter table, which contains PM Statuses of Events
CREATE TABLE #PMSTATUSFILTERTABLE(
VALUEID INT
)

-- Fill table #PMSTATUSFILTERTABLE
INSERT
INTO #PMSTATUSFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@PMSTATUS, N'') AS p

CREATE TABLE #SUMMARYQUALITYANALYSISTMP
(
ID int,
RESOURCE nvarchar(255) collate database_default,
RESTYPE nvarchar(50) collate database_default,
RESCOUNT int,
FAILCOUNT int,
CONNCOUNT int,
PERFCOUNT int,
SECCOUNT int
)

INSERT INTO #SUMMARYQUALITYANALYSISTMP
SELECT
ROW_NUMBER() OVER (ORDER BY COUNT(e.eventid) desc) AS ID,
r.resourceuri AS RESOURCE,
rg.name AS RESTYPE,
COUNT(e.eventid) AS RESCOUNT,
COUNT(CASE aspect WHEN 'applicationfailure' THEN 1 END) AS FAILCOUNT,
COUNT(CASE aspect WHEN 'connectivity' THEN 1 END) AS CONNCOUNT,
COUNT(CASE aspect WHEN 'performance' THEN 1 END) AS PERFCOUNT,
COUNT(CASE aspect WHEN 'security' THEN 1 END) AS SECCOUNT
FROM
APM.event AS e (NOLOCK)
JOIN APM.resource AS r (NOLOCK) on e.resourceid = r.resourceid
JOIN APM.resourcegroup AS rg (NOLOCK) on r.resourcegroupid = rg.resourcegroupid
JOIN #SOURCEMACHINEFILTERTABLE AS f ON (f.TYPEID = 2 AND f.VALUEID = e.MachineId)
JOIN #PMSTATUSFILTERTABLE AS f3 ON (f3.VALUEID = e.PMStatus)
WHERE
((e.aspect = 'performance' AND e.eventduration / 1000000.0 &gt;= @THRESHOLD) OR
e.aspect IN ('applicationfailure', 'connectivity', 'security'))
AND (e.HeavyLight &lt;&gt; 0 OR e.HeavyLight IS NULL)
AND e.sourceId = @SOURCEID
AND e.utceventdate &gt;= @STARTDATE AND e.utceventdate &lt; @ENDDATE
AND (e.category LIKE @PROBLEM OR e.category IS NULL)

GROUP BY
r.resourceuri, rg.name

/*------------------ Base query -------------------------- */
SELECT TOP 5
R1.ID,
R1.RESOURCE,
R1.RESTYPE as RESTYPE,
R1.RESCOUNT,
R1.FAILCOUNT,
R1.CONNCOUNT,
R1.SECCOUNT,
R1.PERFCOUNT,
R1.RESCOUNT + (
SELECT CASE WHEN SUM(r2.RESCOUNT) IS NULL THEN 0 ELSE SUM(r2.RESCOUNT) END
FROM #SUMMARYQUALITYANALYSISTMP r2
WHERE r2.ID &lt; r1.ID
) AS runValue,
SUM(RESCOUNT) OVER() AS AllCount
FROM
#SUMMARYQUALITYANALYSISTMP AS R1
ORDER BY
ID
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.SummarySizeAnalysisReport'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.SummarySizeAnalysisReport AS RETURN 1')
END
GO

/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: SummarySizeAnalysisReport */
/* USED IN: Summary Size Analysis Report */
/* INPUT PARAMETERS: */
/* @STARTDATE - Start date of the priod */
/* @ENDDATE - End date of the period */
/* @SOURCEIDS - List of source Id, separated by comma. Exp: '1,2,3' */
/* @MACHINEIDS - List of machine Id, separated by comma. Exp: '4,5,6' */
/* @ORDERBY - Specifies field to which sorting should be applayed */
/* 1. Page Content Size */
/* 2. Ajax Size */
/* 3. Total Size */
/* 4. Event Count */
/* 5. Event Duration */
/************************************************************************************/
ALTER PROCEDURE APM.SummarySizeAnalysisReport
@STARTDATE DATETIME,
@ENDDATE DATETIME,
@SOURCEIDS NVARCHAR(MAX),
@MACHINEIDS NVARCHAR(MAX),
@ORDERBY INT,
@PMSTATUS NVARCHAR(50)
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON

/****************************************************************************************/
/* ASSISTING TEMP TABLES */
/****************************************************************************************/

-- Filter table, which contains machine ids and source ids
-- typeid defines filter type - 1 for source and 2 for machine
-- valueId filter value - source id and machine id
CREATE TABLE #SOURCEMACHINEFILTERTABLE(
TYPEID INT,
VALUEID INT
)

-- Fill table #SOURCEMACHINEFILTERTABLE
INSERT
INTO #SOURCEMACHINEFILTERTABLE
SELECT
p.typeId AS TYPEID,
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@SOURCEIDS, @MACHINEIDS) AS p

-- Filter table, which contains PM Statuses of Events
CREATE TABLE #PMSTATUSFILTERTABLE(
VALUEID INT
)

-- Fill table #PMSTATUSFILTERTABLE
INSERT
INTO #PMSTATUSFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@PMSTATUS, N'') AS p

CREATE TABLE #CLIENTEVENT
(
CSEVENTID INT,
SOURCEID INT
)

INSERT INTO #CLIENTEVENT
SELECT
CSEVENTID,
SOURCEID
FROM
APM.CSEvent (NOLOCK) AS e
JOIN #SOURCEMACHINEFILTERTABLE AS f1 ON (f1.VALUEID = e.SOURCEID AND f1.TYPEID = 1)
JOIN #SOURCEMACHINEFILTERTABLE AS f2 ON (f2.VALUEID = e.MACHINEID AND f2.TYPEID = 2)
JOIN #PMSTATUSFILTERTABLE AS f3 ON (f3.VALUEID = e.PMSTATUS)
WHERE
e.PAGEURI IS NOT NULL
AND e.CLASSTYPE = N'Performance'
AND e.UTCDATE &gt;= @STARTDATE
AND e.UTCDATE &lt; @ENDDATE

/****************************************************************************************/
/* MAIN QUERY */
/****************************************************************************************/
;WITH AJAXEvents AS
(
SELECT
e.CSEVENTID,
e.SOURCEID,
0 AS IsPageEvent,
ajax.TOTALTIME AS TotalTime,
ajax.RESPONSESIZE + ajax.REQUESTSIZE AS TotalSize
FROM
#CLIENTEVENT AS e
JOIN APM.CSAJAX AS ajax (NOLOCK) ON e.CSEVENTID = ajax.CSEVENTID
),
JSEvents AS
(
SELECT
e.CSEVENTID,
e.SOURCEID,
0 AS IsPageEvent,
js.TOTALTIME AS TotalTime,
NULL AS TotalSize
FROM
#CLIENTEVENT AS e
JOIN APM.CSJSCRIPTEVENT AS js (NOLOCK) ON e.CSEVENTID = js.CSEVENTID
),
PageEvents AS
(
SELECT
e.CSEVENTID,
e.SOURCEID,
1 AS IsPageEvent,
p.TOTALTIME AS TotalTime,
p.TOTALSIZE AS TotalSize
FROM
#CLIENTEVENT AS e
JOIN APM.CSPageEvent AS p (NOLOCK) ON e.CSEVENTID = p.CSEVENTID
),
UnionEvents AS
(
SELECT * FROM AJAXEvents
UNION ALL
SELECT * FROM JSEvents
UNION ALL
SELECT * FROM PageEvents
),
EventAggregation AS
(
SELECT
SOURCEID,
CSEVENTID,
MAX(IsPageEvent) AS IsPageEvent,
MAX(TotalTime) AS TotalTime,
SUM(TotalSize) AS TotalSize
FROM
UnionEvents
GROUP BY
SOURCEID,
CSEVENTID
),
SourceAggregation AS
(
SELECT
SOURCEID,
COUNT(*) AS EventCount,
AVG(TotalTime) / 1000.0 AS EventDuration,
-- Take into account AJAX call size, which occured during page load event
AVG(CASE WHEN IsPageEvent = 1 THEN TotalSize END) / 1024.0 AS PageContentSize,
AVG(TotalSize) / 1024.0 AS TotalSize,
-- Calculate AJAX size only for JS with AJAX and for Asynch AJAX events
AVG(CASE WHEN IsPageEvent = 0 THEN TotalSize END) / 1024.0 AS AjaxSize
FROM
EventAggregation
GROUP BY
SOURCEID
)
SELECT TOP(10)
Row_Number() OVER(ORDER BY
CASE
WHEN @ORDERBY = 1 THEN ds.PageContentSize
WHEN @ORDERBY = 2 THEN ds.AjaxSize
WHEN @ORDERBY = 3 THEN ds.TotalSize
WHEN @ORDERBY = 4 THEN ds.EventCount
WHEN @ORDERBY = 5 THEN ds.EventDuration
END DESC) AS Id,
ds.SOURCEID,
s.SOURCE,
ds.EventCount,
ds.EventDuration,
ds.PageContentSize,
ds.TotalSize,
ds.AjaxSize
FROM
SourceAggregation AS ds
JOIN APM.Source AS s (NOLOCK) ON s.SOURCEID = ds.SOURCEID
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.SummarySizeAnalysisTopAJAXSubReport'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.SummarySizeAnalysisTopAJAXSubReport AS RETURN 1')
END
GO

/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: SummarySizeAnalysisTopAJAXSubReport */
/* USED IN: Summary Size Analysis Sub Report for top AJAX call */
/* INPUT PARAMETERS: */
/* @STARTDATE - Start date of the priod */
/* @ENDDATE - End date of the period */
/* @SOURCEID - Source Id */
/* @MACHINEIDS - List of machine Id, separated by comma. Exp: '4,5,6' */
/************************************************************************************/
ALTER PROCEDURE APM.SummarySizeAnalysisTopAJAXSubReport
@STARTDATE DATETIME,
@ENDDATE DATETIME,
@SOURCEID NVARCHAR(MAX),
@MACHINEIDS NVARCHAR(MAX),
@PMSTATUS NVARCHAR(50)
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON

/****************************************************************************************/
/* ASSISTING TEMP TABLES */
/****************************************************************************************/

-- Filter table, which contains machine ids
-- valueId filter value for machineId
CREATE TABLE #MACHINEFILTERTABLE(
TYPEID INT,
VALUEID INT
)

-- Fill table #SOURCEMACHINEFILTERTABLE
INSERT
INTO #MACHINEFILTERTABLE
SELECT
p.typeId AS TYPEID,
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@MACHINEIDS, N'') AS p

-- Filter table, which contains PM Statuses of Events
CREATE TABLE #PMSTATUSFILTERTABLE(
VALUEID INT
)

-- Fill table #PMSTATUSFILTERTABLE
INSERT
INTO #PMSTATUSFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@PMSTATUS, N'') AS p

CREATE TABLE #AJAXEVENT
(
CSEVENTID INT,
PAGEURI NVARCHAR(255) collate database_default,
AJAXURI NVARCHAR(255) collate database_default,
AJAXDURATION DECIMAL(35, 0),
RESPONSESIZE BIGINT,
REQUESTSIZE BIGINT
)

INSERT INTO #AJAXEVENT
SELECT
e.CSEventId,
e.PageUri,
ajax.Uri,
ajax.TotalTime,
ajax.ResponseSize,
ajax.REQUESTSIZE
FROM
APM.CSEvent (NOLOCK) AS e
JOIN #MACHINEFILTERTABLE AS f ON f.VALUEID = e.MACHINEID
JOIN #PMSTATUSFILTERTABLE AS f1 ON (f1.VALUEID = e.PMSTATUS)
CROSS APPLY (
SELECT TOP(1)
ajax.Uri,
ajax.TotalTime,
ajax.RESPONSESIZE,
ajax.REQUESTSIZE
FROM
APM.CSAJAX AS ajax (NOLOCK)
WHERE
ajax.CSEVENTID = e.CSEVENTID
ORDER BY
ajax.TOTALTIME DESC
) AS ajax
WHERE
e.CLASSTYPE = N'Performance'
AND e.SOURCEID = @SOURCEID
AND e.UTCDATE &gt;= @STARTDATE
AND e.UTCDATE &lt; @ENDDATE
-- collected ajax calls except for page sync ajax calls
AND e.EVENTCLASS &lt;&gt; N'CSMPMonitorLog'

CREATE INDEX idx_Event ON #AJAXEVENT (CSEVENTID)

/****************************************************************************************/
/* MAIN QUERY */
/****************************************************************************************/
;WITH EventDuration AS
(
SELECT
a.CSEVENTID,
a.PAGEURI,
a.AJAXURI,
a.AJAXDURATION AS AJAXDuration,
a.RESPONSESIZE,
a.REQUESTSIZE
FROM
#AJAXEVENT AS a
LEFT OUTER JOIN APM.CSJScriptEvent AS js (NOLOCK) ON a.CSEVENTID = js.cseventid
),
AJAXSize AS
(
SELECT
COUNT(CSEventId) AS EventCount,
PageUri,
AJAXUri,
AVG(AJAXDuration) AS AJAXDuration,
AVG(ResponseSize) AS ResponseSize,
AVG(RequestSize) AS RequestSize,
AVG(ResponseSize + RequestSize) AS TotalSize
FROM
EventDuration
GROUP BY
PageUri,
AJAXUri
),
NumberedRow AS
(
SELECT
Row_Number() OVER(ORDER BY TotalSize DESC) AS Id,
EventCount,
PageUri,
AJAXUri,
AJAXDuration/1000.0 AS AJAXDuration,
ResponseSize/1024.0 AS ResponseSize,
RequestSize/1024.0 AS RequestSize,
TotalSize/1024.0 AS TotalSize,
SUM(EventCount) OVER() AS TotalEventCount
FROM
AJAXSize
)
SELECT TOP(4)
Id,
EventCount,
PageUri,
AJAXUri AS AjaxCall,
AJAXDuration,
ResponseSize,
RequestSize,
TotalSize,
TotalEventCount
FROM
NumberedRow
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.SummarySizeAnalysisTopPagesSubReport'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.SummarySizeAnalysisTopPagesSubReport AS RETURN 1')
END
GO

/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: SummarySizeAnalysisTopPagesSubReport */
/* USED IN: Summary Size Analysis Sub Report for top pages */
/* INPUT PARAMETERS: */
/* @STARTDATE - Start date of the priod */
/* @ENDDATE - End date of the period */
/* @SOURCEID - Source Id */
/* @MACHINEIDS - List of machine Id, separated by comma. Exp: '4,5,6' */
/* @ORDERBY - Specifies field to which sorting should be applayed */
/* 1. Image Size */
/* 2. CssStyle Size */
/* 3. Htc Size */
/* 4. Script Size */
/* 5. HTML Size */
/* 6. AjaxSize Size */
/* 7. TotalSize Size */
/* 8. Event Count */
/* 9. Avg. Event Duration */
/************************************************************************************/
ALTER PROCEDURE APM.SummarySizeAnalysisTopPagesSubReport
@STARTDATE DATETIME,
@ENDDATE DATETIME,
@SOURCEID INT,
@MACHINEIDS NVARCHAR(MAX),
@ORDERBY INT,
@PMSTATUS NVARCHAR(50)
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON

/****************************************************************************************/
/* ASSISTING TEMP TABLES */
/****************************************************************************************/

-- Filter table, which contains machine ids
-- valueId filter value for machineid
CREATE TABLE #MACHINEFILTERTABLE(
VALUEID INT
)

-- Fill table #SOURCEMACHINEFILTERTABLE
INSERT
INTO #MACHINEFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@MACHINEIDS, N'') AS p

-- Filter table, which contains PM Statuses of Events
CREATE TABLE #PMSTATUSFILTERTABLE(
VALUEID INT
)

-- Fill table #PMSTATUSFILTERTABLE
INSERT
INTO #PMSTATUSFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@PMSTATUS, N'') AS p

CREATE TABLE #PAGEEVENT
(
CSEVENTID INT,
PAGEURI NVARCHAR(255) collate database_default,
TOTALTIME DECIMAL(35, 0),
TOTALSIZE DECIMAL(35, 0)
)

INSERT INTO #PAGEEVENT
SELECT
e.CSEVENTID,
e.PAGEURI,
P.TOTALTIME,
P.TOTALSIZE
FROM
APM.CSEvent (NOLOCK) AS e
JOIN #MACHINEFILTERTABLE AS f ON (f.VALUEID = e.MACHINEID)
JOIN #PMSTATUSFILTERTABLE AS f1 ON (f1.VALUEID = e.PMSTATUS)
JOIN APM.CSPageEvent AS p (NOLOCK) ON p.CSEventId = e.CSEVENTID
WHERE
e.PAGEURI IS NOT NULL
AND e.SOURCEID = @SOURCEID
AND e.CLASSTYPE = N'Performance'
AND e.SOURCEID &lt;&gt; -1
AND e.UTCDATE &gt;= @STARTDATE
AND e.UTCDATE &lt; @ENDDATE

/****************************************************************************************/
/* MAIN QUERY */
/****************************************************************************************/
--Before grouping by page uri, event content with Null size should by transformed to 0,
-- to provide convergence with Avg total size
;WITH PeripheralSize AS
(
SELECT
e.CSEVENTID,
SUM(CASE WHEN p.TYPE = N'Image' THEN p.TotalSize END) AS Image,
SUM(CASE WHEN p.TYPE = N'Script' THEN p.TotalSize END) AS Script,
SUM(CASE WHEN p.TYPE = N'CssStyle' THEN p.TotalSize END) AS CssStyle,
SUM(CASE WHEN p.TYPE = N'HtcBehavior' THEN p.TotalSize END) AS HtcBehavior,
SUM(CASE WHEN p.TYPE = N'HTML' THEN p.TotalSize END) AS HTML
FROM
APM.CSPeripheral AS p (NOLOCK)
JOIN #PAGEEVENT AS e ON p.cseventid = e.CSEVENTID
GROUP BY
e.CSEVENTID
),
PageSize AS
(
SELECT
e.PAGEURI,
COUNT(e.CSEVENTID) AS EventCount,
AVG(COALESCE(p.Image, 0)) AS Image,
AVG(COALESCE(p.Script, 0)) AS Script,
AVG(COALESCE(p.CssStyle, 0)) AS CssStyle,
AVG(COALESCE(p.HtcBehavior, 0)) AS HtcBehavior,
AVG(COALESCE(p.HTML, 0)) AS HTML,
AVG(e.TOTALTIME) AS EventDuration,
AVG(e.TOTALSIZE) AS TotalSize
FROM
#PAGEEVENT AS e
LEFT OUTER JOIN PeripheralSize AS p ON p.CSEventid = e.CSEVENTID
GROUP BY
e.PAGEURI
),
AJAXSize AS
(
SELECT
a.PageUri,
AVG(a.AjaxSize) AS AjaxSize
FROM
(
SELECT
e.CSEVENTID,
e.PAGEURI,
SUM(COALESCE(ajax.ResponseSize + ajax.REQUESTSIZE, 0)) AS AjaxSize
FROM
#PAGEEVENT AS e
JOIN APM.CSAJAX AS ajax (NOLOCK) ON (ajax.CSEventId = e.CSEVENTID)
GROUP BY
e.CSEVENTID,
e.PAGEURI
) AS a
GROUP BY
a.PageUri
),
NumberedResults AS
(
SELECT
Row_Number() OVER(ORDER BY
CASE
WHEN @ORDERBY = 1 THEN p.Image
WHEN @ORDERBY = 2 THEN p.CssStyle
WHEN @ORDERBY = 3 THEN p.HtcBehavior
WHEN @ORDERBY = 4 THEN p.Script
WHEN @ORDERBY = 5 THEN p.HTML
WHEN @ORDERBY = 6 THEN ajax.AjaxSize
WHEN @ORDERBY = 7 THEN p.TotalSize + COALESCE(ajax.AjaxSize, 0)
WHEN @ORDERBY = 8 THEN p.EventCount
WHEN @ORDERBY = 9 THEN p.EventDuration
END DESC) AS Id,
p.PageUri,
p.EventCount,
p.Image/(1024.0) AS Image,
p.Script/(1024.0) AS Script,
p.CssStyle/(1024.0) AS CssStyle,
p.HtcBehavior/(1024.0) AS HtcBehavior,
p.HTML/(1024.0) AS HTML,
p.EventDuration/(1000.0) AS EventDuration,
(p.TotalSize + COALESCE(ajax.AjaxSize, 0))/(1024.0) AS TotalSize,
COALESCE(ajax.AjaxSize, 0)/(1024.0) AS AjaxSize,
SUM(p.EventCount) OVER() AS TotalEventCount
FROM
PageSize AS p
LEFT OUTER JOIN AJAXSize AS ajax ON Ajax.PageUri = p.PageUri
)
SELECT TOP(4)
Id,
PageUri,
EventCount,
Image,
Script,
CssStyle,
HtcBehavior,
HTML,
EventDuration,
TotalSize,
AjaxSize,
TotalEventCount
FROM
NumberedResults
ORDER BY
Id
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.TopUserPerformanceIssues'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.TopUserPerformanceIssues AS RETURN 1')
END
GO

/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: TopUserPerformanceIssues */
/* USED IN: Top5UserPerformanceSubReport.rdl */
/* INPUT PARAMETERS: */
/* @SOURCEID - Source id */
/* @COMPUTERIDS - List of the computer id, separated by comma. Exp: '1,2,3' */
/* @STARTDATE - Start date of the period */
/* @ENDDATE - End date of the period */
/* @TRESHOLD - Event duration treshold */
/************************************************************************************/
ALTER PROCEDURE [APM].[TopUserPerformanceIssues]
(
@SOURCEIDS NVARCHAR(MAX),
@COMPUTERIDS NVARCHAR(MAX),
@STARTDATE DATETIME,
@ENDDATE DATETIME,
@THRESHOLD INT,
@USERNAME NVARCHAR(255),
@PMSTATUS NVARCHAR(50)
) WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON

/************************************************************************************/
/* ASSISTING TEMP TABLES */
/************************************************************************************/

-- Filter table, which contains machine ids and source ids
-- typeid defines filter type - 1 for source and 2 for machine
-- valueId filter value - source id and machine id
CREATE TABLE #SOURCEMACHINEFILTERTABLE(
TYPEID INT,
VALUEID INT
)

-- Fill table #SOURCEMACHINEFILTERTABLE
INSERT
INTO #SOURCEMACHINEFILTERTABLE
SELECT
p.typeId AS TYPEID,
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@SOURCEIDS, @COMPUTERIDS) AS p

-- Filter table, which contains PM Statuses of Events
CREATE TABLE #PMSTATUSFILTERTABLE(
VALUEID INT
)

-- Fill table #PMSTATUSFILTERTABLE
INSERT
INTO #PMSTATUSFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@PMSTATUS, N'') AS p

CREATE TABLE #SUMUSERANALYSIS
(
DESCRIPTION nvarchar(255) collate database_default,
USERID int,
USERFLAG BIT,
SOURCEID int,
EVENTCOUNT int,
USERSUMSLOWESTNODEDUR decimal(35,0),
USERCOUNTSLOWESTNODEDUR int,
SLOWESTNODEDUR decimal(35,0),
COUNTSLOWESTNODDUR int
)

-- Select performance event information for all users
;WITH UsersInfo AS
(
SELECT
pn.description AS Description,
MIN(e.UserId) AS UserId,
CASE u.Name WHEN @USERNAME THEN 1 ELSE 0 END AS UserFlag,
e.sourceId,
COUNT(e.EVENTID) AS EventCount,
SUM(CASE u.Name WHEN @USERNAME THEN pn.selfduration END) AS UserSumSlowestNodeDur,
COUNT(CASE u.Name WHEN @USERNAME THEN e.EVENTID END) AS UserCountSlowestNodeDur,
SUM(pn.selfduration) AS SlowestNodeDur,
COUNT(pn.selfduration) AS CountSlowestNodeDur
FROM
APM.EVENT AS e
JOIN #SOURCEMACHINEFILTERTABLE AS f1 ON (f1.TYPEID = 1 AND f1.VALUEID = e.SourceId)
JOIN #SOURCEMACHINEFILTERTABLE AS f2 ON (f2.TYPEID = 2 AND f2.VALUEID = e.MachineId)
JOIN #PMSTATUSFILTERTABLE AS f3 ON (f3.VALUEID = e.PMStatus)
CROSS APPLY(SELECT TOP(1) pn1.SelfDuration, pn1.Description
FROM
APM.PerformanceNode AS pn1
WHERE
pn1.eventid = e.eventid
AND pn1.resourceid = e.resourceid
ORDER BY
pn1.SelfDuration DESC) AS pn
JOIN APM.Users AS u ON e.userid = u.userid
WHERE
E.UTCEVENTDATE &gt; @STARTDATE
AND E.UTCEVENTDATE &lt; @ENDDATE
AND E.EVENTDURATION / 1000000.0 &gt;= @THRESHOLD
AND E.ASPECT = N'performance'
AND COALESCE(E.HeavyLight, 1) &lt;&gt; 0

GROUP BY
e.sourceid,
pn.description,
u.name
)
INSERT #SUMUSERANALYSIS
SELECT
DESCRIPTION,
USERID,
USERFLAG,
SOURCEID,
EVENTCOUNT,
USERSUMSLOWESTNODEDUR,
USERCOUNTSLOWESTNODEDUR,
SLOWESTNODEDUR,
COUNTSLOWESTNODEDUR
FROM UsersInfo

CREATE INDEX temp1_idx ON #SUMUSERANALYSIS(DESCRIPTION, SOURCEID) INCLUDE (USERID, EVENTCOUNT, SLOWESTNODEDUR)

-- Select information for current user
;WITH OrderedDataSet AS
(
SELECT
u.DESCRIPTION,
u.SOURCEID,
u.EVENTCOUNT,
CASE
WHEN u.USERCOUNTSLOWESTNODEDUR &lt;&gt;0 THEN u.USERSUMSLOWESTNODEDUR / (u.USERCOUNTSLOWESTNODEDUR * 1000)
ELSE 0
END AS SlowestNodeDur
FROM
#SUMUSERANALYSIS AS u
WHERE
u.USERFLAG = 1
),
--Select top 5 performance event for user
TopDataSet AS
(
SELECT TOP 5
ROW_NUMBER() OVER(ORDER BY EventCount DESC) AS id,
1 AS UserId,
description,
sourceId,
EventCount,
SlowestNodeDur,
EventCount AS SumEventCount,
SUM(EventCount) OVER() AS TotalEventCount,
0 AS UsersAffected
FROM
OrderedDataSet
),
-- Calculate information for all users, but only for top 5 performence events
EachUserInfo AS
(
SELECT
f.Id,
UserStat.DESCRIPTION,
UserStat.SOURCEID,
UserStat.EVENTCOUNT,
UserStat.SLOWESTNODEDUR,
UserStat.USERID
FROM
#SUMUSERANALYSIS UserStat
JOIN TopDataSet AS f ON (f.SOURCEID = UserStat.SOURCEID AND UserStat.DESCRIPTION = f.DESCRIPTION)
),
OtherUsersInfo AS
(
SELECT
MAX(Id) AS Id,
2 AS UserId,
description,
sourceId,
AVG(EventCount * 1.0) AS EventCount,
SUM(SlowestNodeDur)/1000.0/SUM(EventCount) AS SlowestNodeDur,
0 AS SumEventCount,
0 AS TotalEventCount,
COUNT(DISTINCT COALESCE(userid,0)) AS UsersAffected
FROM
EachUserInfo
GROUP BY
sourceId,
description
),
[Result] AS
(
SELECT *
FROM
TopDataSet
UNION
SELECT *
FROM
OtherUsersInfo
)
SELECT
r.Id,
r.UserId,
r.description,
s.Source,
r.EventCount,
r.SlowestNodeDur,
r.SumEventCount,
r.TotalEventCount,
r.UsersAffected
FROM
[Result] r
JOIN APM.Source (NOLOCK) AS s ON s.SourceId = r.SourceId
ORDER BY
Id, UserId
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.TopUserExceptionIssues'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.TopUserExceptionIssues AS RETURN 1')
END
GO

/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: TopUserExceptionIssues */
/* USED IN: Top5UserExceptionSubReport.rdl */
/* INPUT PARAMETERS: */
/* @SOURCEID - Source id */
/* @COMPUTERIDS - List of the computer id, separated by comma. Exp: '1,2,3' */
/* @STARTDATE - Start date of the period */
/* @ENDDATE - End date of the period */
/************************************************************************************/
ALTER PROCEDURE [APM].[TopUserExceptionIssues]
(
@SOURCEIDS NVARCHAR(MAX),
@COMPUTERIDS NVARCHAR(MAX),
@STARTDATE DATETIME,
@ENDDATE DATETIME,
@USERNAME NVARCHAR(255),
@PMSTATUS NVARCHAR(50)
) WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON
/************************************************************************************/
/* ASSISTING TEMP TABLES */
/************************************************************************************/

-- Filter table, which contains machine ids and source ids
-- typeid defines filter type - 1 for source and 2 for machine
-- valueId filter value - source id and machine id
CREATE TABLE #SOURCEMACHINEFILTERTABLE(
TYPEID INT,
VALUEID INT
)

-- Fill table #SOURCEMACHINEFILTERTABLE
INSERT
INTO #SOURCEMACHINEFILTERTABLE
SELECT
p.typeId AS TYPEID,
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@SOURCEIDS, @COMPUTERIDS) AS p

-- Filter table, which contains PM Statuses of Events
CREATE TABLE #PMSTATUSFILTERTABLE(
VALUEID INT
)

-- Fill table #PMSTATUSFILTERTABLE
INSERT
INTO #PMSTATUSFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@PMSTATUS, N'') AS p

CREATE TABLE #SUMUSERANALYSIS
(
DESCRIPTION nvarchar(255) collate database_default,
USERID int,
USERFLAG BIT,
SOURCEID int,
EVENTCOUNT int,
SECURITYFAILURE int,
APPLICATIONFAILURE int,
CONNECTIVITYFAILURE int
)

--Select information about events for all users
;WITH UsersInfo AS
(
SELECT
e.DESCRIPTION AS DESCRIPTION,
MIN(e.USERID) AS USERID,
CASE u.Name WHEN @USERNAME THEN 1 ELSE 0 END AS USERFLAG,
e.SOURCEID,
COUNT(e.EVENTID) AS EVENTCOUNT,
COUNT(CASE WHEN e.ASPECT = N'security' THEN e.EVENTID END) AS SECURITYFAILURE,
COUNT(CASE WHEN e.ASPECT = N'applicationfailure' THEN e.EVENTID END) AS APPLICATIONFAILURE,
COUNT(CASE WHEN e.ASPECT = N'connectivity' THEN e.EVENTID END) AS CONNECTIVITYFAILURE
FROM
APM.EVENT AS e
--JOIN ExceptionNode AS en ON (en.eventid = e.eventid and en.resourceid = e.resourceid)
JOIN #SOURCEMACHINEFILTERTABLE AS f1 ON (f1.TYPEID = 1 AND f1.VALUEID = e.SourceId)
JOIN #SOURCEMACHINEFILTERTABLE AS f2 ON (f2.TYPEID = 2 AND f2.VALUEID = e.MachineId)
JOIN #PMSTATUSFILTERTABLE AS f3 ON (f3.VALUEID = e.PMStatus)
JOIN APM.Users AS u ON e.USERID = u.USERID
WHERE
e.UTCEVENTDATE &gt; @STARTDATE
AND e.UTCEVENTDATE &lt; @ENDDATE
AND e.ASPECT IN ( N'security',N'applicationfailure',N'connectivity')

GROUP BY
e.SOURCEID,
e.DESCRIPTION,
u.NAME
)
INSERT #SUMUSERANALYSIS
SELECT
Description,
UserId,
UserFlag,
SourceId,
EventCount,
SecurityFailure,
ApplicationFailure,
ConnectivityFailure
FROM UsersInfo

CREATE INDEX temp1_idx ON #SUMUSERANALYSIS(DESCRIPTION, SOURCEID)

-- Select event information for current user only (condition UserFlag = 1 allows to filter event by current user)
;WITH OrderedDataSet AS
(
SELECT
ROW_NUMBER() OVER(ORDER BY EVENTCOUNT DESC) AS ID,
DESCRIPTION,
SOURCEID,
EVENTCOUNT,
SECURITYFAILURE,
APPLICATIONFAILURE,
CONNECTIVITYFAILURE,
SUM(EVENTCOUNT) OVER() AS TOTALEVENTCOUNT
FROM
#SUMUSERANALYSIS AS u
WHERE
USERFLAG = 1
),
--Select top 5 exception events for current user
TopDataSet AS
(
SELECT
TOP(5)
id,
1 AS UserId,
description,
sourceId,
EventCount,
SecurityFailure,
ApplicationFailure,
ConnectivityFailure,
EventCount AS SumEventCount,
TotalEventCount,
0 AS UsersAffected
FROM
OrderedDataSet AS U
ORDER BY Id
),
-- Select information about same exceptions for other users
EachUserInfo AS
(
SELECT
f.ID,
UserStat.DESCRIPTION,
UserStat.SOURCEID,
UserStat.EVENTCOUNT,
UserStat.SECURITYFAILURE,
UserStat.APPLICATIONFAILURE,
UserStat.CONNECTIVITYFAILURE,
UserStat.USERID
FROM
#SUMUSERANALYSIS UserStat
JOIN TopDataSet AS f ON (f.SOURCEID = UserStat.SOURCEID AND UserStat.DESCRIPTION = f.DESCRIPTION)
),
OtherUsersInfo AS
(
SELECT
MAX(Id) AS Id,
2 AS UserId,
description,
sourceId,
AVG(EventCount * 1.0) AS EventCount,
AVG(SecurityFailure * 1.0) AS SecurityFailure,
AVG(ApplicationFailure * 1.0) AS ApplicationFailure,
AVG(ConnectivityFailure * 1.0) AS ConnectivityFailure,
0 AS SumEventCount,
0 AS TotalEventCount,
COUNT(DISTINCT COALESCE(userid,0)) AS UsersAffected
FROM
EachUserInfo
GROUP BY
sourceId,
description
),
-- Unify information about current user and all users
[Result] AS (
SELECT *
FROM
TopDataSet
UNION ALL
SELECT *
FROM
OtherUsersInfo
)
SELECT
r.Id,
r.UserId,
r.description,
s.Source,
r.EventCount,
r.SecurityFailure,
r.ApplicationFailure,
r.ConnectivityFailure,
r.SumEventCount,
r.TotalEventCount,
r.UsersAffected
FROM
[Result] r
JOIN apm.Source (NOLOCK) AS s ON s.SourceId = r.SourceId
ORDER BY
Id, UserId
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.SummaryPerformanceAnalysisReport'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.SummaryPerformanceAnalysisReport AS RETURN 1')
END
GO

/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: SummaryPerformanceAnalysisReport */
/* USED IN: Summary Performance Analysis Report */
/* INPUT PARAMETERS: */
/* @STARTDATE - Start date of the priod */
/* @ENDDATE - End date of the period */
/* @SOURCEIDS - List of source Id, separated by comma. Exp: '1,2,3' */
/* @MACHINEIDS - List of machine Id, separated by comma. Exp: '4,5,6' */
/* @INCLUDESUBNET - Subnet masks list, which should be included */
/* @EXCLUDESUBNET - Subnet mask list, which should be excluded */
/* @THRESHOLD - Event threshold */
/* @ORDERBY - Specifies field to which sorting should be applayed */
/* 1. Request Count (temporary obsolete) */
/* 2. Problems Count */
/* 3. Event Count */
/* 4. MAX Event Duration */
/* 5. AVG Event Duration */
/* 6. Event Size */
/************************************************************************************/
ALTER PROCEDURE APM.SummaryPerformanceAnalysisReport
@STARTDATE DATETIME,
@ENDDATE DATETIME,
@SOURCEIDS NVARCHAR(MAX),
@MACHINEIDS NVARCHAR(MAX),
@INCLUDESUBNET NVARCHAR(MAX),
@EXCLUDESUBNET NVARCHAR(MAX),
@THRESHOLD INT,
@PMSTATUS NVARCHAR(50),
@ORDERBY INT
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON

/****************************************************************************************/
/* ASSISTING TEMP TABLES */
/****************************************************************************************/

SELECT
@INCLUDESUBNET = REPLACE(@INCLUDESUBNET, N'*', N'%'),
@EXCLUDESUBNET = REPLACE(@EXCLUDESUBNET, N'*', N'%')

-- Filter table, which contains machine ids and source ids
-- typeid defines filter type - 1 for source and 2 for machine
-- valueId filter value - source id and machine id
CREATE TABLE #SOURCEMACHINEFILTERTABLE(
TYPEID INT,
VALUEID INT
)

-- Fill table #SOURCEMACHINEFILTERTABLE
INSERT
INTO #SOURCEMACHINEFILTERTABLE
SELECT
p.typeId AS TYPEID,
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@SOURCEIDS, @MACHINEIDS) AS p

-- Filter table for SubnetC values
CREATE TABLE #SUBNETCFILTERTABLE
(
IPID INT
)

-- Insert into filter id of the SubnetC to increase performence for event table
INSERT INTO #SUBNETCFILTERTABLE
SELECT DISTINCT
ipid
FROM
IP AS ip (NOLOCK)
JOIN APM.GetMultiParameters(CASE WHEN LEN(@INCLUDESUBNET) &gt; 0 THEN @INCLUDESUBNET ELSE N'%' END, N'') AS p1 ON (ip.SubnetC LIKE p1.Value)
LEFT OUTER JOIN APM.GetMultiParameters(CASE WHEN LEN(@EXCLUDESUBNET) &gt; 0 THEN @EXCLUDESUBNET ELSE N'Fake' END, N'') AS p2 ON (ip.SubnetC LIKE p2.Value)
WHERE
--Exclude subnets which have correspondance in @EXCLUDESUBNET parameter
p2.typeId IS NULL

-- Filter table, which contains PM Statuses of Events
CREATE TABLE #PMSTATUSFILTERTABLE(
VALUEID INT
)

-- Fill table #PMSTATUSFILTERTABLE
INSERT
INTO #PMSTATUSFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@PMSTATUS, N'') AS p

CREATE TABLE #CLIENTEVENT
(
CSEVENTID INT,
CSEVENTGROUPID INT,
EVENTCLASS NVARCHAR(50),
SOURCEID INT
)

INSERT INTO #CLIENTEVENT
SELECT
e.CSEVENTID,
e.CSEVENTGROUPID,
e.EVENTCLASS,
e.SOURCEID
FROM
APM.CSEvent (NOLOCK) AS e
JOIN #SOURCEMACHINEFILTERTABLE AS f1 ON (f1.VALUEID = e.SourceId AND f1.TYPEID = 1)
JOIN #SOURCEMACHINEFILTERTABLE AS f2 ON (f2.VALUEID = e.MachineId AND f2.TYPEID = 2)
JOIN #SUBNETCFILTERTABLE AS f3 ON e.ipid = f3.IPID
JOIN #PMSTATUSFILTERTABLE AS f4 ON (f4.VALUEID = e.PMStatus)
WHERE
e.ClassType = N'Performance'
AND e.UTCDate &gt;= @STARTDATE
AND e.UTCDate &lt; @ENDDATE

/****************************************************************************************************************/
/* MAIN QUERY */
/****************************************************************************************************************/
;WITH AJAXEvents AS
(
SELECT
E.CSEVENTID,
SUM(COALESCE(ajax.REQUESTSIZE, 0))+ SUM(COALESCE(ajax.ResponseSize, 0)) AS AjaxSize,
-- This field will be used only for Asynch Ajax, and for Asycnch Ajax CSAJAX table
-- contains only one row for each event, so sum doesn't make any difference
SUM(ajax.TotalTime) AS TotalTime
FROM
#CLIENTEVENT AS e
JOIN APM.CSAJAX AS ajax ON e.CSEVENTID = ajax.CSEventId
GROUP BY
e.CSEVENTID

),
CSEvents AS
(
SELECT
e.CSEVENTID,
e.CSEVENTGROUPID,
e.SOURCEID,
js.CSEventId AS JavaScriptEventId,
(CASE WHEN ((js.CSEventId IS NULL) AND (e.EVENTCLASS =N'CSMAMonitorLog')) THEN e.CSEVENTID ELSE NULL END) AS AsyncAjaxEventId,
(CASE WHEN ((js.CSEventId IS NULL) AND (e.EVENTCLASS =N'CSMPMonitorLog')) THEN e.CSEVENTID ELSE NULL END) AS PageEventId,
COALESCE(pe.TotalTime, COALESCE(js.TotalTime, ajax.TotalTime)) AS EventDuration,
COALESCE(pe.TotalSize, ajax.AjaxSize) AS EventSize
FROM
#CLIENTEVENT AS e
LEFT OUTER JOIN APM.CSJSCRIPTEVENT AS js (NOLOCK) ON js.CSEventId = e.CSEVENTID
LEFT OUTER JOIN AJAXEvents AS ajax (NOLOCK) ON ajax.CSEventId = e.CSEVENTID
LEFT OUTER JOIN APM.CSPAGEEVENT AS pe (NOLOCK) ON pe.CSEventId = e.CSEVENTID
),
SourceStat AS
(
SELECT
SourceId,
COUNT(JavaScriptEventId) AS JavaScriptEventCount,
COUNT(AsyncAjaxEventId) AS AsyncAjaxEventCount,
COUNT(PageEventId) AS PageEventCount,
COUNT(CSEventId) AS EventCount,
COUNT(DISTINCT CSEventGroupId) AS ProblemsCount,
MAX(EventDuration) AS MAXEventDuration,
AVG(EventDuration) AS AVGEventDuration,
AVG(EventSize) AS EventSize
FROM
CSEvents
WHERE
EventDuration / 1000.0 &gt;= @THRESHOLD
GROUP BY
SourceId
),
NumberedSources AS
(
SELECT
ROW_NUMBER() OVER(ORDER BY (CASE @ORDERBY
WHEN 2 THEN e.ProblemsCount
WHEN 3 THEN e.EventCount
WHEN 4 THEN e.MAXEventDuration
WHEN 5 THEN e.AVGEventDuration
WHEN 6 THEN e.EventSize
END) DESC) Id,
e.SourceId,
s.Source,
e.JavaScriptEventCount,
e.AsyncAjaxEventCount,
e.PageEventCount,
e.EventCount,
e.ProblemsCount,
e.MAXEventDuration/1000.0 AS MAXEventDuration,
e.AVGEventDuration/1000.0 AS AVGEventDuration,
-- Temporary obsolete field, return appropriate value, than it will be returned
1 AS requestCount,
e.EventSize/1024.0 AS EventSize,
SUM(e.EventCount) OVER() AS TotalEventCount
FROM
SourceStat AS e
JOIN APM.Source AS s (NOLOCK) ON e.SourceId = s.SourceId
)
SELECT TOP (10) *
FROM
NumberedSources
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.SummaryPerformanceAnalysisReportMaxScale'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.SummaryPerformanceAnalysisReportMaxScale AS RETURN 1')
END
GO

/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: SummaryPerformanceAnalysisReportMaxScale */
/* USED IN: Summary Performance Analysis Report */
/* INPUT PARAMETERS: */
/* @STARTDATE - Start date of the priod */
/* @ENDDATE - End date of the period */
/* @SOURCEIDS - List of source Id, separated by comma. Exp: '1,2,3' */
/* @MACHINEIDS - List of machine Id, separated by comma. Exp: '4,5,6' */
/* @INCLUDESUBNET - Subnet masks list, which should be included */
/* @EXCLUDESUBNET - Subnet mask list, which should be excluded */
/* @THRESHOLD - Event threshold */
/************************************************************************************/

ALTER PROCEDURE APM.SummaryPerformanceAnalysisReportMaxScale
@STARTDATE DATETIME,
@ENDDATE DATETIME,
@SOURCEIDS NVARCHAR(MAX),
@MACHINEIDS NVARCHAR(MAX),
@INCLUDESUBNET NVARCHAR(MAX),
@EXCLUDESUBNET NVARCHAR(MAX),
@PMSTATUS NVARCHAR(50),
@THRESHOLD INT
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON

/****************************************************************************************/
/* ASSISTING TEMP TABLES */
/****************************************************************************************/

-- Filter table, which contains machine ids and source ids
-- typeid defines filter type - 1 for source and 2 for machine
-- valueId filter value - source id and machine id
CREATE TABLE #SOURCEMACHINEFILTERTABLE(
TYPEID INT,
VALUEID INT
)

SELECT
@INCLUDESUBNET = REPLACE(@INCLUDESUBNET, N'*', N'%'),
@EXCLUDESUBNET = REPLACE(@EXCLUDESUBNET, N'*', N'%')


-- Fill table #SOURCEMACHINEFILTERTABLE
INSERT
INTO #SOURCEMACHINEFILTERTABLE
SELECT
p.typeId AS TYPEID,
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@SOURCEIDS, @MACHINEIDS) AS p

-- Filter table, which contains PM Statuses of Events
CREATE TABLE #PMSTATUSFILTERTABLE(
VALUEID INT
)

-- Fill table #PMSTATUSFILTERTABLE
INSERT
INTO #PMSTATUSFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@PMSTATUS, N'') AS p

-- Filter table for SubnetC values
CREATE TABLE #SUBNETCFILTERTABLE
(
IPID INT
)

-- Insert into filter id of the SubnetC to increase performence for event table
INSERT INTO #SUBNETCFILTERTABLE
SELECT DISTINCT
ipid
FROM
IP AS ip (NOLOCK)
JOIN APM.GetMultiParameters(CASE WHEN LEN(@INCLUDESUBNET) &gt; 0 THEN @INCLUDESUBNET ELSE N'%' END, N'') AS p1 ON (ip.SubnetC LIKE p1.Value)
LEFT OUTER JOIN APM.GetMultiParameters(CASE WHEN LEN(@EXCLUDESUBNET) &gt; 0 THEN @EXCLUDESUBNET ELSE N'Fake' END, N'') AS p2 ON (ip.SubnetC LIKE p2.Value)
WHERE
--Exclude subnets which have correspondance in @EXCLUDESUBNET parameter
p2.typeId IS NULL

CREATE TABLE #CLIENTEVENT
(
CSEVENTID INT,
CSEVENTGROUPID INT,
EVENTCLASS NVARCHAR(50) COLLATE database_default,
SOURCEID INT,
PAGEURI NVARCHAR(255) COLLATE database_default
)

INSERT INTO #CLIENTEVENT
SELECT
e.CSEVENTID,
e.CSEVENTGROUPID,
e.EVENTCLASS,
e.SOURCEID,
e.PAGEURI
FROM
APM.CSEvent (NOLOCK) AS e
JOIN #SOURCEMACHINEFILTERTABLE AS f1 ON (f1.VALUEID = e.SOURCEID AND f1.TYPEID = 1)
JOIN #SOURCEMACHINEFILTERTABLE AS f2 ON (f2.VALUEID = e.MACHINEID AND f2.TYPEID = 2)
JOIN #SUBNETCFILTERTABLE AS f3 ON e.IPID = f3.IPID
JOIN #PMSTATUSFILTERTABLE AS f4 ON (f4.VALUEID = e.PMSTATUS)
WHERE
e.CLASSTYPE = N'Performance'
AND e.PAGEURI IS NOT NULL
AND e.UTCDATE &gt;= @STARTDATE
AND e.UTCDATE &lt; @ENDDATE

;WITH JSAndAJAXEvent AS
(
SELECT
e.CSEVENTID,
e.SOURCEID,
e.PAGEURI,
COALESCE(js.TotalTime, ajax.TotalTime) AS EventDuration,
COALESCE(js.Action, ajax.Uri) AS Action
FROM
#CLIENTEVENT AS e
LEFT OUTER JOIN APM.CSJScriptEvent AS js (NOLOCK) ON js.CSEVENTID = e.CSEVENTID
LEFT OUTER JOIN APM.CSAJAX AS ajax (NOLOCK) ON ajax.CSEVENTID = e.CSEVENTID
WHERE
EVENTCLASS = N'CSMAMonitorLog'
AND COALESCE(js.TotalTime, ajax.TOTALTIME)/1000.0 &gt;= @THRESHOLD
),
-- As main query shows only top 10 sources,
-- this should be take into account for choosing max durations
SourceFilter AS
(
SELECT
ROW_NUMBER() OVER(ORDER BY COUNT(e.CSEVENTID) DESC) AS SourceRowNumber,
e.SOURCEID
FROM
#CLIENTEVENT AS e
GROUP BY
e.SOURCEID
),
JSAndAJAXEventsDuration AS
(
SELECT
ROW_NUMBER() OVER(PARTITION BY E.SourceId ORDER BY COUNT(e.CSEventId) DESC) AS Id,
e.SOURCEID,
e.PAGEURI,
e.Action,
COUNT(e.CSEVENTID) AS EventCount,
AVG(EventDuration) AS EventDuration
FROM
JSAndAJAXEvent AS e
JOIN SourceFilter AS s ON s.SOURCEID = e.SOURCEID
WHERE
s.SourceRowNumber &lt;= 10
GROUP BY
e.SOURCEID,
e.PAGEURI,
e.Action
),
PageEvent AS
(
SELECT ROW_NUMBER() OVER(PARTITION BY e.SOURCEID ORDER BY COUNT(e.CSEVENTID) DESC) AS Id,
e.SOURCEID,
COUNT(e.CSEVENTID) AS EventCount,
AVG(pe.TOTALTIME) AS EventDuration,
e.PAGEURI
FROM
#CLIENTEVENT AS e
JOIN APM.CSPAGEEVENT AS pe (NOLOCK) ON pe.CSEVENTID = e.CSEVENTID
JOIN SourceFilter AS s ON s.SOURCEID = e.SOURCEID
WHERE
pe.TOTALTIME/1000.0 &gt;=@THRESHOLD
AND s.SourceRowNumber &lt;= 10
GROUP BY
e.SOURCEID,
e.PAGEURI
)
SELECT
(
SELECT
COALESCE(MAX(EventDuration),0)/1000.0
FROM
PageEvent
WHERE
Id &lt;= 5
)AS MaxPageEventDuration,
(
SELECT
COALESCE(MAX(EventDuration),0)/1000.0
FROM
JSAndAJAXEventsDuration
WHERE
Id &lt;= 5
)AS MaxJSEventDuration
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.LoadTimeAnalysisBasedOnSubNet'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.LoadTimeAnalysisBasedOnSubNet AS RETURN 1')
END
GO

/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: LoadTimeAnalysisBasedOnSubNet */
/* USED IN: Load Time Analysis Based On Subnet as main data set query */
/* INPUT PARAMETERS: */
/* @STARTDATE - Start date of the priod */
/* @ENDDATE - End date of the period */
/* @SOURCEID - SourceId */
/* @MACHINEIDS - List of machine Id, separated by comma. Exp: '4,5,6' */
/* @INCLUDESUBNET - Subnet masks list, which should be included */
/* @EXCLUDESUBNET - Subnet mask list, which should be excluded */
/* @THRESHOLD - Event threshold */
/* @ORDERBY - Specifies field to which sorting should be applayed */
/* 1. Request Count (temporary obsolete) */
/* 2. Problems Count */
/* 4. Avg Event Duration */
/* 5. Latency */
/************************************************************************************/

ALTER PROCEDURE APM.LoadTimeAnalysisBasedOnSubNet
@STARTDATE DATETIME,
@ENDDATE DATETIME,
@SOURCEID NVARCHAR(MAX),
@MACHINEIDS NVARCHAR(MAX),
@INCLUDESUBNET NVARCHAR(MAX),
@EXCLUDESUBNET NVARCHAR(MAX),
@THRESHOLD INT,
@ORDERBY INT,
@PMSTATUS NVARCHAR(50)
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON

/****************************************************************************************/
/* ASSISTING TEMP TABLES */
/****************************************************************************************/

SELECT
@INCLUDESUBNET = REPLACE(@INCLUDESUBNET, N'*', N'%'),
@EXCLUDESUBNET = REPLACE(@EXCLUDESUBNET, N'*', N'%')

-- Filter table, which contains machine ids and source ids
-- valueId filter value - machine id
CREATE TABLE #MACHINEFILTERTABLE(
VALUEID INT
)

-- Fill table #SOURCEMACHINEFILTERTABLE
INSERT
INTO #MACHINEFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@MACHINEIDS, N'') AS p

-- Filter table, which contains PM Statuses of Events
CREATE TABLE #PMSTATUSFILTERTABLE(
VALUEID INT
)

-- Fill table #PMSTATUSFILTERTABLE
INSERT
INTO #PMSTATUSFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@PMSTATUS, N'') AS p

-- Filter table for SubnetC values
CREATE TABLE #SUBNETCFILTERTABLE
(
IPID INT,
SUBNETC NVARCHAR(50) COLLATE database_default
)

-- Insert into filter id of the SubnetC to increase performance for event table
INSERT INTO #SUBNETCFILTERTABLE
SELECT DISTINCT
IPID,
SUBNETC
FROM
APM.IP AS ip (NOLOCK)
JOIN APM.GetMultiParameters(CASE WHEN LEN(@INCLUDESUBNET) &gt; 0 THEN @INCLUDESUBNET ELSE N'%' END, N'') AS p1 ON (ip.SUBNETC LIKE p1.Value)
LEFT OUTER JOIN APM.GetMultiParameters(CASE WHEN LEN(@EXCLUDESUBNET) &gt; 0 THEN @EXCLUDESUBNET ELSE N'Fake' END, N'') AS p2 ON (ip.SUBNETC LIKE p2.Value)
WHERE
--Exclude subnets which have correspondance in @EXCLUDESUBNET parameter
p2.typeId IS NULL

CREATE TABLE #CLIENTEVENT
(
CSEVENTID INT,
CSEVENTGROUPID INT,
EVENTCLASS NVARCHAR(50) COLLATE database_default ,
SUBNETC NVARCHAR(50) COLLATE database_default
)

INSERT INTO #CLIENTEVENT
SELECT
e.CSEVENTID,
e.CSEVENTGROUPID,
e.EVENTCLASS,
f2.SUBNETC
FROM
APM.CSEvent (NOLOCK) AS e
JOIN #MACHINEFILTERTABLE AS f ON (f.VALUEID = e.MACHINEID)
JOIN #SUBNETCFILTERTABLE AS f2 ON e.IPID = f2.IPID
JOIN #PMSTATUSFILTERTABLE AS f3 ON (f3.VALUEID = e.PMSTATUS)
WHERE
e.CLASSTYPE = N'Performance'
AND e.PAGEURI IS NOT NULL
AND e.SOURCEID = @SOURCEID
AND e.UTCDATE &gt;= @STARTDATE
AND e.UTCDATE &lt; @ENDDATE

/****************************************************************************************/
/* MAIN QUERY */
/****************************************************************************************/
;WITH AJAXEvent AS
(
SELECT
e.CSEVENTID,
e.SUBNETC,
ajax.Synchronous,
SUM(ajax.NetworkTime) AS NetworkTime,
SUM(ajax.ServerTime) AS ServerTime,
SUM(ajax.ResponseTime) AS ResponseTime,
AVG(ajax.Latency) AS Latency,
SUM(ajax.TotalTime) AS TotalTime
FROM
#CLIENTEVENT AS e
JOIN APM.CSAJAX AS ajax (NOLOCK) ON ajax.CSEventId = e.CSEVENTID
GROUP BY
e.CSEVENTID,
e.SUBNETC,
ajax.Synchronous

),
ClientEvents AS
(
SELECT
e.SUBNETC,
e.CSEVENTID,
e.CSEVENTGROUPID,
-- if JScript table has corresponding row (not null value), than consider it is java script event
js.CSEventId AS JavaScriptEventId,
-- If it is not JavaScript event, then define its type by event class type
(CASE WHEN ((js.CSEventId IS NULL) AND (e.EVENTCLASS =N'CSMAMonitorLog')) THEN e.CSEVENTID ELSE NULL END) AS AsyncAjaxEventId,
(CASE WHEN ((js.CSEventId IS NULL) AND (e.EVENTCLASS =N'CSMPMonitorLog')) THEN e.CSEVENTID ELSE NULL END) AS PageEventId,
-- Define duration by joined table. As Page Event, Asynch Ajax and Java script
-- events are mutually exclusive it can be done as folllows
COALESCE(p.TotalTime, COALESCE(js.TotalTime, ajax.TotalTime)) AS EventDuration,
p.NetworkTime AS PageLoadNetworkTime,
p.ServerTime AS PageLoadServerTime,
p.DOMTime AS PageDOMLoad,
p.PeripheralTime AS PagePeripheralTime,
p.OnLoadTime AS PageOnLoadTime,
p.TotalTime AS PageEventTime,
(ajax.NetworkTime + ajax.ResponseTime) AS AjaxNetworkTime,
ajax.ServerTime AS AjaxServerTime,
-- If event is asynch ajax, then there is no corresponding row in JavaScript table,
-- If it is synch ajax, then its total duration should be taken from java script total time
COALESCE(js.TotalTime, ajax.TotalTime) AS AjaxTotalTime,
-- Client time should be calculated as total time, minus network, server and response time,
-- But total time should be taken not from ajax table, it is depend on event type
COALESCE(js.TotalTime, ajax.TotalTime)
-- For AJAX event ther could by no corresponding row in AJAX table, then all time consider to be Client
- COALESCE(ajax.NetworkTime + ajax.ResponseTime + ajax.ServerTime, 0) AS AjaxClientTime,
--Latency belongs either to page event or to Ajax event
COALESCE(p.Latency, ajax.Latency) AS Latency,
COUNT(e.CSEVENTID) OVER() AS TotalEventCount
FROM
#CLIENTEVENT AS e
LEFT OUTER JOIN AJAXEvent AS ajax ON ajax.CSEventId = e.CSEVENTID
LEFT OUTER JOIN APM.CSPageEvent AS p (NOLOCK) ON P.CSEventId = e.CSEVENTID
LEFT OUTER JOIN APM.CSJScriptEvent AS js (NOLOCK) ON js.CSEventId = e.CSEVENTID
WHERE
COALESCE(p.TotalTime, COALESCE(js.TotalTime, ajax.TotalTime)) / 1000.0 &gt;= @THRESHOLD
),
-- Aggregate data for each subnet
SubnetSummary AS
(
SELECT
SubnetC,
COUNT(CSEventId) AS EventCount,
COUNT(DISTINCT CSEventGroupId) AS ProblemCount,
-- For counting events by types, use that COUNT does not calculates null values
COUNT(JavaScriptEventId) AS JSEventCount,
COUNT(AsyncAjaxEventId) AS AsynchAjaxEvent,
COUNT(PageEventId) AS PageEventCount,
AVG(PageLoadNetworkTime)/1000.0 AS PageLoadNetworkTime,
AVG(PageLoadServerTime)/1000.0 AS PageLoadServerTime,
AVG(PageDOMLoad)/1000.0 AS PageDOMLoad,
AVG(PagePeripheralTime)/1000.0 AS PagePeripheralTime,
AVG(PageOnLoadTime)/1000.0 AS PageOnLoadTime,
AVG(Latency) AS Latency,
AVG(AjaxNetworkTime)/1000.0 AS AjaxNetworkTime,
AVG(AjaxServerTime)/1000.0 AS AjaxServerTime,
AVG(AjaxClientTime)/1000.0 AS ClientTime,
AVG(EventDuration)/1000.0 AS AvgEventDuration,
-- This aggregation has no difference as it is same for all rows
MAX(TotalEventCount) AS TotalEventCount
FROM
ClientEvents
GROUP BY
SubnetC
)
SELECT TOP(20)
row_number() OVER(ORDER BY (CASE @ORDERBY
WHEN 1 THEN ProblemCount
WHEN 2 THEN EventCount
WHEN 3 THEN coalesce(PageLoadServerTime, 0) + coalesce(AjaxServerTime, 0)
WHEN 4 THEN AvgEventDuration
WHEN 5 THEN Latency
END) DESC) Id,
SubnetC,
EventCount,
ProblemCount,
PageEventCount,
JSEventCount,
AsynchAjaxEvent,
PageLoadNetworkTime,
PageLoadServerTime,
PageDOMLoad,
PagePeripheralTime,
PageOnLoadTime,
AjaxNetworkTime,
AjaxServerTime,
ClientTime,
Latency,
AvgEventDuration,
TotalEventCount
FROM
SubnetSummary
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.LoadTimeAnalysisBasedOnSubNetMaxScale'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.LoadTimeAnalysisBasedOnSubNetMaxScale AS RETURN 1')
END
GO

/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: LoadTimeAnalysisBasedOnSubNet */
/* USED IN: Load Time Analysis Based On Subnet for calculating max value in */
/* subreports, to make one scaling for all sub reports */
/* INPUT PARAMETERS: */
/* @STARTDATE - Start date of the priod */
/* @ENDDATE - End date of the period */
/* @SOURCEID - SourceId */
/* @MACHINEIDS - List of machine Id, separated by comma. Exp: '4,5,6' */
/* @INCLUDESUBNET - Subnet masks list, which should be included */
/* @EXCLUDESUBNET - Subnet mask list, which should be excluded */
/************************************************************************************/
alter PROCEDURE APM.LoadTimeAnalysisBasedOnSubNetMaxScale
@STARTDATE DATETIME,
@ENDDATE DATETIME,
@SOURCEID NVARCHAR(MAX),
@MACHINEIDS NVARCHAR(MAX),
@INCLUDESUBNET NVARCHAR(MAX),
@EXCLUDESUBNET NVARCHAR(MAX),
@PMSTATUS NVARCHAR(50)
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON
/****************************************************************************************/
/* ASSISTING TEMP TABLES */
/****************************************************************************************/

SELECT
@INCLUDESUBNET = REPLACE(@INCLUDESUBNET, N'*', N'%'),
@EXCLUDESUBNET = REPLACE(@EXCLUDESUBNET, N'*', N'%')

-- Filter table, which contains machine ids and source ids
-- valueId filter value - machine id
CREATE TABLE #MACHINEFILTERTABLE(
VALUEID INT
)

-- Fill table #SOURCEMACHINEFILTERTABLE
INSERT
INTO #MACHINEFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@MACHINEIDS, N'') AS p

-- Filter table, which contains PM Statuses of Events
CREATE TABLE #PMSTATUSFILTERTABLE(
VALUEID INT
)

-- Fill table #PMSTATUSFILTERTABLE
INSERT
INTO #PMSTATUSFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@PMSTATUS, N'') AS p

CREATE TABLE #IPFILTER
(
IPID INT
)

INSERT INTO #IPFILTER
SELECT DISTINCT
ipid
FROM
apm.IP AS ip (NOLOCK)
JOIN APM.GetMultiParameters(CASE WHEN LEN(@INCLUDESUBNET) &gt; 0 THEN @INCLUDESUBNET ELSE N'%' END, N'') AS p1 ON (ip.SubnetC LIKE p1.Value)
LEFT OUTER JOIN APM.GetMultiParameters(CASE WHEN LEN(@EXCLUDESUBNET) &gt; 0 THEN @EXCLUDESUBNET ELSE N'Fake' END, N'') AS p2 ON (ip.SubnetC LIKE p2.Value)
WHERE
--Exclude subnets which have correspondance in @EXCLUDESUBNET parameter
p2.typeId IS NULL

CREATE TABLE #CLIENTEVENT
(
CSEVENTID INT,
EVENTCLASS NVARCHAR(50) COLLATE database_default,
PAGEURI NVARCHAR(255) COLLATE database_default,
SUBNETC NVARCHAR(50) COLLATE database_default
)

INSERT INTO #CLIENTEVENT
SELECT
e.CSEVENTID,
e.EVENTCLASS,
e.PAGEURI,
ip.SUBNETC
FROM
-- Max values should be selected not only for appropriate subnetc, but for all
-- (as in subreports, relative values to other is shown). So filtering by subnets could not be hold here
APM.CSEvent (NOLOCK) AS e
JOIN #MACHINEFILTERTABLE AS f ON (f.VALUEID = e.MACHINEID)
JOIN #IPFILTER AS f2 ON (e.IPID = f2.IPID)
JOIN #PMSTATUSFILTERTABLE AS f3 ON (f3.VALUEID = e.PMSTATUS)
JOIN APM.IP AS ip (NOLOCK) ON ip.IPID = e.IPID

WHERE
e.CLASSTYPE = N'Performance'
AND e.PAGEURI IS NOT NULL
AND e.SOURCEID = @SOURCEID
AND e.UTCDATE &gt;= @STARTDATE
AND e.UTCDATE &lt; @ENDDATE

-- Filter table for SubnetC values
CREATE TABLE #SUBNETCFILTERTABLE
(
SUBNETC NVARCHAR(50) COLLATE database_default
)

-- In report shown only top 20 subnets by event count
-- Besides, user specifies filter by subnet, so select subnets, for which MAX should be selected
INSERT INTO #SUBNETCFILTERTABLE
SELECT
TOP(20)
e.SUBNETC
FROM
#CLIENTEVENT AS e
GROUP BY
e.SUBNETC
ORDER BY
COUNT(e.CSEVENTID) DESC


/****************************************************************************************/
/* MAIN QUERIES */
/****************************************************************************************/
;WITH AJAXEvents AS
(
SELECT
e.CSEVENTID,
-- This field need only for asynch ajax events, and for this type here can by only one row,
-- so aggregation doesn't matter
MAX(ajax.URI) AS AjaxAction,
SUM(ajax.TOTALTIME) AS TotalTime
FROM
#CLIENTEVENT AS e
JOIN APM.CSAJAX AS ajax (NOLOCK) ON ajax.CSEVENTID = e.CSEVENTID
WHERE
e.EVENTCLASS = N'CSMAMonitorLog' OR e.EVENTCLASS = N'CSMSMonitorLog'
GROUP BY
e.CSEVENTID
),
JSEvents AS
(
SELECT
e.CSEVENTID,
e.SUBNETC,
e.PAGEURI,
COALESCE(js.ACTION, ajax.AjaxAction) AS Action,
COALESCE(js.TOTALTIME, ajax.TotalTime) AS EventDuration,
--Calculate average event duration for all subnets
AVG(COALESCE(js.TOTALTIME, ajax.TotalTime)) OVER(PARTITION BY e.PAGEURI,
COALESCE(js.Action, ajax.AjaxAction)) AS CommonDuration
FROM
#CLIENTEVENT AS e
LEFT OUTER JOIN APM.CSJScriptEvent AS js (NOLOCK) ON js.CSEVENTID = e.CSEVENTID
LEFT OUTER JOIN AJAXEvents AS ajax ON ajax.CSEVENTID = e.CSEVENTID
WHERE
e.EVENTCLASS = N'CSMAMonitorLog' OR e.EVENTCLASS = N'CSMSMonitorLog'
),
JSActionsForSubnets AS
(
SELECT
ROW_NUMBER() OVER(PARTITION BY js.SUBNETC ORDER BY COUNT(CSEVENTID) DESC) AS Id,
COUNT(CSEVENTID) AS EventCount,
js.SUBNETC,
Action,
PAGEURI,
MAX(CommonDuration) AS CommonDuration,
AVG(EventDuration) AS AvgActionDuration
FROM
JSEvents AS js
JOIN #SUBNETCFILTERTABLE AS f ON f.SUBNETC = js.SUBNETC
GROUP BY
js.SUBNETC,
PageUri,
Action
),
PageEvents AS
(
SELECT
e.CSEVENTID,
e.PAGEURI,
e.SUBNETC,
p.TOTALTIME,
--Calculate Average page load duration for all subnets
AVG(p.TOTALTIME) OVER(PARTITION BY e.PAGEURI) AS PageAvgDuration
FROM
#CLIENTEVENT AS e
JOIN APM.CSPageEvent AS p (NOLOCK) ON e.CSEVENTID = p.CSEVENTID
),
PageEventsForSubNets AS
(
SELECT
ROW_NUMBER() OVER(PARTITION BY e.SUBNETC ORDER BY COUNT(e.CSEVENTID) DESC) AS Id,
e.SUBNETC,
e.PAGEURI,
AVG(e.TOTALTIME) AS PageAvgSubNetDuration,
MAX(e.PageAvgDuration) AS PageAvgDuration
FROM
PageEvents AS e
JOIN #SUBNETCFILTERTABLE AS f ON f.SUBNETC = e.SUBNETC
GROUP BY
e.SUBNETC,
e.PAGEURI
)
SELECT
(SELECT COALESCE(MAX(CASE WHEN CommonDuration &gt;= AvgActionDuration THEN CommonDuration ELSE AvgActionDuration END)/1000.0, 0)
FROM
JSActionsForSubnets
WHERE Id &lt;= 5) AS MaxAjaxDuration,
(SELECT COALESCE(MAX(CASE WHEN PageAvgDuration &gt;= PageAvgSubNetDuration THEN PageAvgDuration ELSE PageAvgSubNetDuration END)/1000.0, 0)
FROM
PageEventsForSubNets
WHERE Id &lt;= 5) AS MaxPageLoadDuration
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.LoadTimeAnalysisBasedOnSubNetTopJSAndAJAXCalls'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.LoadTimeAnalysisBasedOnSubNetTopJSAndAJAXCalls AS RETURN 1')
END
GO

/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: LoadTimeAnalysisBasedOnSubNetTopJSAndAJAXCalls */
/* USED IN: Load Time Analysis Based On Subnet for Top JS ajax calls subreport */
/* INPUT PARAMETERS: */
/* @STARTDATE - Start date of the priod */
/* @ENDDATE - End date of the period */
/* @SOURCEID - SourceId */
/* @MACHINEIDS - List of machine Id, separated by comma. Exp: '4,5,6' */
/* @SUBNETC - SubnetC for which data should be selected */
/* @THRESHOLD - Event threshold */
/************************************************************************************/
alter PROCEDURE APM.LoadTimeAnalysisBasedOnSubNetTopJSAndAJAXCalls
@STARTDATE DATETIME,
@ENDDATE DATETIME,
@SOURCEID NVARCHAR(MAX),
@MACHINEIDS NVARCHAR(MAX),
@SUBNETC NVARCHAR(25),
@THRESHOLD INT,
@PMSTATUS NVARCHAR(50)
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON

/****************************************************************************************/
/* ASSISTING TEMP TABLES */
/****************************************************************************************/

-- Filter table, which contains machine ids and source ids
-- valueId filter value - machine id
CREATE TABLE #MACHINEFILTERTABLE(
VALUEID INT
)

-- Fill table #SOURCEMACHINEFILTERTABLE
INSERT
INTO #MACHINEFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@MACHINEIDS, N'') AS p

-- Filter table, which contains PM Statuses of Events
CREATE TABLE #PMSTATUSFILTERTABLE(
VALUEID INT
)

-- Fill table #PMSTATUSFILTERTABLE
INSERT
INTO #PMSTATUSFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@PMSTATUS, N'') AS p

CREATE TABLE #CLIENTEVENTFORALLSUBNETS
(
CSEVENTID INT,
PAGEURI NVARCHAR(255) collate database_default,
SUBNETC NVARCHAR(50) collate database_default
)

-- Filter Event Table by incoming parameters
-- Filtering by SubnetC is not made here, as relative time information
-- for all other sources should be also calculated
INSERT INTO #CLIENTEVENTFORALLSUBNETS
SELECT
e.CSEventId,
e.PageUri,
ip.SubNetC
FROM
APM.CSEvent (NOLOCK) AS e
JOIN #MACHINEFILTERTABLE AS f ON (f.VALUEID = e.MachineId)
JOIN #PMSTATUSFILTERTABLE AS f1 ON (f1.VALUEID = e.PMStatus)
JOIN APM.IP (NOLOCK) ON ip.ipid = e.ipid
WHERE
e.SourceId = @SOURCEID
--Select only Asynch AJAX and JS events
AND (e.EventClass = N'CSMAMonitorLog' OR e.EventClass = N'CSMSMonitorLog')
AND e.UTCDate &gt;= @STARTDATE
AND e.UTCDate &lt; @ENDDATE
AND PageUri IS NOT NULL

-- Events should be selected only for that pages, which are actual for specified @SUBNETC
-- If for the @SUBNETC there is no one event for some page, events for this page should not be selected at all
CREATE TABLE #CLIENTEVENTFILTEREDBYPAGEURI
(
CSEVENTID INT,
PAGEURI NVARCHAR(255) COLLATE database_default,
SUBNETC NVARCHAR(50) COLLATE database_default
)

INSERT INTO #CLIENTEVENTFILTEREDBYPAGEURI
SELECT
e.CSEVENTID,
e.PAGEURI,
e.SUBNETC
FROM
#CLIENTEVENTFORALLSUBNETS AS e
WHERE
e.SUBNETC = @SUBNETC
AND e.PAGEURI IN (SELECT
e1.PAGEURI
FROM
#CLIENTEVENTFORALLSUBNETS AS e1
WHERE
e1.SUBNETC = @SUBNETC
)

/********************************************************************************************************/
/* MAIN QUERY */
/********************************************************************************************************/
;WITH AJAXEvents AS
(
SELECT
e.CSEVENTID,
e.PAGEURI,
e.SUBNETC,
-- This field need only for asynch ajax events, and for this type here can by only one row,
-- so aggregation doesn't matter
MAX(ajax.Uri) AS AjaxAction,
SUM(ajax.ServerTime) AS ServerTime,
SUM(ajax.NetworkTime + ajax.ResponseTime) AS NetworkTime,
SUM(ajax.TotalTime) AS TotalTime,
SUM(COALESCE(ajax.REQUESTSIZE, 0) + COALESCE(ajax.ResponseSize, 0)) AS CallSize
FROM
#CLIENTEVENTFILTEREDBYPAGEURI AS e
JOIN APM.CSAJAX AS ajax (NOLOCK) ON e.CSEVENTID = ajax.CSEventId
GROUP BY
e.CSEVENTID,
e.PAGEURI,
e.SUBNETC
),
CSJSEvents AS
(
SELECT
e.PAGEURI,
e.SUBNETC,
e.CSEVENTID,
COALESCE(js.Action, ajax.AjaxAction) AS AjaxAction,
COALESCE(js.TotalTime, ajax.TotalTime)/1000.0 AS TotalTime,
COALESCE(ajax.NetworkTime, 0)/1000.0 AS NetworkTime,
COALESCE(ajax.ServerTime, 0)/1000.0 AS ServerTime,
-- don't change size to 0, as average size should be calculated only for ajax calls, not all events
ajax.CallSize/1024.0 AS CallSize
FROM
#CLIENTEVENTFILTEREDBYPAGEURI AS e
LEFT OUTER JOIN APM.CSJScriptEvent AS js (NOLOCK) ON js.CSEventid = e.CSEVENTID
LEFT OUTER JOIN AJAXEvents AS ajax (NOLOCK) ON ajax.CSEventid = e.CSEVENTID
WHERE
-- Threshold condition should be applied only for Asynch Ajax Events,
-- For Synch Ajax this condition is applied to JS event
COALESCE(js.TotalTime, ajax.TotalTime)/1000.0 &gt;= @THRESHOLD
),
AJAXActionInfo AS
(
SELECT
PageUri,
AjaxAction,
COUNT(CASE WHEN Subnetc = @SUBNETC THEN CSEventId END) AS EventCount,
AVG(CASE WHEN Subnetc = @SUBNETC THEN NetworkTime END) AS NetworkTime,
AVG(CASE WHEN Subnetc = @SUBNETC THEN ServerTime END) AS ServerTime,
AVG(CASE WHEN Subnetc = @SUBNETC THEN TotalTime - (NetworkTime + ServerTime) END) AS ClientTime,
AVG(CASE WHEN Subnetc = @SUBNETC THEN TotalTime END) AS TotalTime,
AVG(CASE WHEN Subnetc = @SUBNETC THEN CallSize END) AS AJAXCallSize,
AVG(NetworkTime) AS CommonNetworkTime,
AVG(ServerTime) AS CommonServerTime,
AVG(TotalTime - (NetworkTime + ServerTime)) AS CommonClientTime,
AVG(TotalTime) AS CommonTotalTime
FROM
CSJSEvents
GROUP BY
PageUri,
AjaxAction
),
OrderedActions AS
(
SELECT
ROW_NUMBER() OVER(ORDER BY EventCount DESC) AS id,
EventCount,
AjaxAction,
pageUri,
ClientTime,
NetworkTime,
ServerTime,
TotalTime,
CommonClientTime,
CommonNetworkTime,
CommonServerTime,
CommonTotalTime,
AJAXCallSize,
SUM(EventCount) OVER() AS TotalEvents
FROM
AJAXActionInfo
)
--Second row is used to show relative AJAX execution time for other subnets
SELECT
d.id,
rowId.n AS rowId,
d.pageUri,
d.AjaxAction,
(CASE WHEN rowId.n = 1 THEN d.EventCount ELSE 0 END )AS EventCount,
(CASE WHEN rowId.n = 1 THEN d.ClientTime ELSE d.CommonClientTime END )AS ClientTime,
(CASE WHEN rowId.n = 1 THEN d.NetworkTime ELSE d.CommonNetworkTime END )AS NetworkTime,
(CASE WHEN rowId.n = 1 THEN d.ServerTime ELSE d.CommonServerTime END )AS ServerTime,
(CASE WHEN rowId.n = 1 THEN d.TotalTime ELSE d.CommonTotalTime END) AS TotalTime,
(CASE WHEN rowId.n = 1 THEN d.AJAXCallSize ELSE 0 END )AS AJAXCallSize,
(CASE WHEN rowId.n = 1 THEN d.TotalEvents ELSE 0 END )AS TotalEvents
FROM
APM.fn_nums(2) AS rowId,
OrderedActions AS d
WHERE
d.id &lt;= 5
ORDER BY
id,
rowId
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.LoadTimeAnalysisBasedOnSubNetTopPages'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.LoadTimeAnalysisBasedOnSubNetTopPages AS RETURN 1')
END
GO

/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: LoadTimeAnalysisBasedOnSubNetTopPages */
/* USED IN: Load Time Analysis Based On Subnet for Top pages subreport */
/* INPUT PARAMETERS: */
/* @STARTDATE - Start date of the priod */
/* @ENDDATE - End date of the period */
/* @SOURCEID - SourceId */
/* @MACHINEIDS - List of machine Id, separated by comma. Exp: '4,5,6' */
/* @SUBNETC - SubnetC for which data should be selected */
/* @THRESHOLD - Event threshold */
/************************************************************************************/
ALTER PROCEDURE APM.LoadTimeAnalysisBasedOnSubNetTopPages
@STARTDATE DATETIME,
@ENDDATE DATETIME,
@SOURCEID NVARCHAR(MAX),
@MACHINEIDS NVARCHAR(MAX),
@SUBNETC NVARCHAR(25),
@THRESHOLD INT,
@PMSTATUS NVARCHAR(50)
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON

/****************************************************************************************/
/* ASSISTING TEMP TABLES */
/****************************************************************************************/

-- Filter table, which contains machine ids and source ids
-- valueId filter value - machine id
CREATE TABLE #MACHINEFILTERTABLE(
VALUEID INT
)

-- Fill table #SOURCEMACHINEFILTERTABLE
INSERT
INTO #MACHINEFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@MACHINEIDS, N'') AS p

-- Filter table, which contains PM Statuses of Events
CREATE TABLE #PMSTATUSFILTERTABLE(
VALUEID INT
)

-- Fill table #PMSTATUSFILTERTABLE
INSERT
INTO #PMSTATUSFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@PMSTATUS, N'') AS p

CREATE TABLE #CLIENTEVENTFORALLSUBNETS
(
CSEVENTID INT,
PAGEURI NVARCHAR(255) COLLATE database_default,
SUBNETC NVARCHAR(50) COLLATE database_default
)

-- Filter Event Table by incoming parameters
-- Filtering by SubnetC is not made here, as relative time information
-- for all other sources should be also calculated
INSERT INTO #CLIENTEVENTFORALLSUBNETS
SELECT
e.CSEventId,
e.PageUri,
ip.SubNetC
FROM
APM.CSEvent (NOLOCK) AS e
JOIN #MACHINEFILTERTABLE AS f ON (f.VALUEID = e.MachineId)
JOIN #PMSTATUSFILTERTABLE AS f1 ON (f1.VALUEID = e.PMStatus)
JOIN APM.IP (NOLOCK) ON ip.ipid = e.ipid
WHERE
e.SourceId = @SOURCEID
AND e.EventClass = N'CSMPMonitorLog'
AND e.UTCDate &gt;= @STARTDATE
AND e.UTCDate &lt; @ENDDATE
AND PageUri IS NOT NULL

-- Events should be selected only for that pages, which are actual for specified @SUBNETC
-- If for the @SUBNETC there is no one event for some page, events for this page should not be selected at all
;WITH CSPageEvents AS
(
SELECT
e.CSEVENTID,
e.PAGEURI,
pe.NetworkTime,
pe.ServerTime,
pe.DOMTime,
pe.PeripheralTime,
pe.OnLoadTime,
pe.TotalTime,
pe.TotalSize,
e.SUBNETC
FROM
#CLIENTEVENTFORALLSUBNETS (NOLOCK) AS e
JOIN APM.CSPageEvent AS pe ON pe.cseventid = e.CSEVENTID
WHERE
e.PAGEURI IN (SELECT DISTINCT
e1.PAGEURI
FROM
#CLIENTEVENTFORALLSUBNETS AS e1
WHERE
e1.SUBNETC = @SUBNETC
)
AND pe.TotalTime/1000.0 &gt; @THRESHOLD
),
PageProcessingTime AS
(
SELECT
PageUri,
COUNT(CASE WHEN Subnetc = @SUBNETC THEN CSEVENTID END) AS EventCount,
AVG(CASE WHEN Subnetc = @SUBNETC THEN COALESCE(NetworkTime, 0) END)/1000 AS NetworkTime,
AVG(CASE WHEN Subnetc = @SUBNETC THEN COALESCE(ServerTime, 0) END)/1000 AS ServerTime,
AVG(CASE WHEN Subnetc = @SUBNETC THEN COALESCE(DOMTime, 0) END)/1000 AS DOMTime,
AVG(CASE WHEN Subnetc = @SUBNETC THEN COALESCE(PeripheralTime, 0) END)/1000 AS PeripheralTime,
AVG(CASE WHEN Subnetc = @SUBNETC THEN COALESCE(OnLoadTime, 0) END)/1000 AS OnLoadTime,
AVG(CASE WHEN Subnetc = @SUBNETC THEN COALESCE(TotalTime, 0) END)/1000 AS TotalTime,
AVG(CASE WHEN Subnetc = @SUBNETC THEN COALESCE(TotalSize, 0) END)/1024.0 AS TotalSize,
AVG(NetworkTime)/1000 AS CommonNetworkTime,
AVG(ServerTime)/1000 AS CommonServerTime,
AVG(DOMTime)/1000 AS CommonDOMTime,
AVG(PeripheralTime)/1000 AS CommonPeripheralTime,
AVG(OnLoadTime)/1000 AS CommonOnLoadTime,
AVG(TotalTime)/1000 AS CommonTotalTime
FROM
CSPageEvents
GROUP BY
PageUri
),
NumberedPages AS
(
SELECT
row_number() OVER(ORDER BY EventCount DESC) AS id,
PageUri,
EventCount,
NetworkTime,
ServerTime,
DOMTime,
PeripheralTime,
OnLoadTime,
TotalTime,
TotalSize,
CommonNetworkTime,
CommonServerTime,
CommonDOMTime,
CommonPeripheralTime,
CommonOnLoadTime,
CommonTotalTime,
SUM(EventCount) OVER() AS TotalEvents
FROM
PageProcessingTime
),
OneRowData AS
(
SELECT
TOP(5)
id,
PageUri,
EventCount,
NetworkTime,
ServerTime,
DOMTime,
PeripheralTime,
OnLoadTime,
TotalTime,
TotalSize,
CommonNetworkTime,
CommonServerTime,
CommonDOMTime,
CommonPeripheralTime,
CommonOnLoadTime,
(COALESCE(CommonNetworkTime, 0) + COALESCE(CommonServerTime, 0)+ COALESCE(CommonDOMTime, 0) + COALESCE(CommonPeripheralTime, 0) + COALESCE(CommonOnLoadTime, 0)) AS CommonTotalTime,
TotalEvents
FROM
NumberedPages
WHERE
EventCount &gt; 0
ORDER BY id
)
--Second row is used to show relative Page Load time for other subnets
SELECT
d.id,
rowId.n AS rowId,
d.PageUri,
(CASE WHEN rowId.n = 1 THEN d.EventCount ELSE 0 END )AS EventCount,
(CASE WHEN rowId.n = 1 THEN d.NetworkTime ELSE d.CommonNetworkTime END )AS NetworkTime,
(CASE WHEN rowId.n = 1 THEN d.ServerTime ELSE d.CommonServerTime END )AS ServerTime,
(CASE WHEN rowId.n = 1 THEN d.DOMTime ELSE d.CommonDOMTime END )AS DOMTime,
(CASE WHEN rowId.n = 1 THEN d.PeripheralTime ELSE d.CommonPeripheralTime END )AS PeripheralTime,
(CASE WHEN rowId.n = 1 THEN d.OnLoadTime ELSE d.CommonOnLoadTime END )AS OnLoadTime,
(CASE WHEN rowId.n = 1 THEN d.TotalTime ELSE d.CommonTotalTime END )AS TotalTime,
(CASE WHEN rowId.n = 1 THEN d.TotalSize ELSE d.TotalSize END )AS TotalSize,
(CASE WHEN rowId.n = 1 THEN d.TotalEvents ELSE d.TotalEvents END )AS TotalEvents,
--Get ajax call flag
CASE WHEN EXISTS(
SELECT *
FROM #CLIENTEVENTFORALLSUBNETS c
JOIN APM.CSAJAX AS csaj (NOLOCK) ON csaj.cseventid = c.CSEVENTID
WHERE d.PageUri = c.PAGEURI
) THEN '*' ELSE ''
END AS Extension
FROM
APM.fn_nums(2) AS rowId,
OneRowData AS d
ORDER BY
id,
rowId
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.ClientLatencyDistributionBySources'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.ClientLatencyDistributionBySources AS RETURN 1')
END
GO

/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME:ClientLatencyDistributionBySources */
/* USED IN: Client Latency Distribution for summary table by sources */
/* INPUT PARAMETERS: */
/* @STARTDATE - Start date of the priod */
/* @ENDDATE - End date of the period */
/* @SOURCEIDS - List of source Id, separated by comma. Exp: '1,2,3' */
/* @MACHINEIDS - List of machine Id, separated by comma. Exp: '4,5,6' */
/* @SUBNETC - List subnet type C, selected by user */
/* @ORDERBY - Specifies latency range to which ordering should be applied */
/************************************************************************************/

ALTER PROCEDURE APM.ClientLatencyDistributionBySources
@STARTDATE DATETIME,
@ENDDATE DATETIME,
@SOURCEIDS NVARCHAR(MAX),
@MACHINEIDS NVARCHAR(MAX),
@INCLUDESUBNET NVARCHAR(MAX),
@EXCLUDESUBNET NVARCHAR(MAX),
@PMSTATUS NVARCHAR(50),
@ORDERBY INT
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON

/****************************************************************************************/
/* ASSISTING TEMP TABLES */
/****************************************************************************************/
SELECT
@INCLUDESUBNET = REPLACE(@INCLUDESUBNET, N'*', N'%'),
@EXCLUDESUBNET = REPLACE(@EXCLUDESUBNET, N'*', N'%')

-- Filter table, which contains machine ids and source ids
-- typeid defines filter type - 1 for source and 2 for machine
-- valueId filter value - source id and machine id
CREATE TABLE #SOURCEMACHINEFILTERTABLE(
TYPEID INT,
VALUEID INT
)

-- Fill table #SOURCEMACHINEFILTERTABLE
INSERT
INTO #SOURCEMACHINEFILTERTABLE
SELECT
p.typeId AS TYPEID,
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@SOURCEIDS, @MACHINEIDS) AS p


-- Filter table, which contains PM Statuses of Events
CREATE TABLE #PMSTATUSFILTERTABLE(
VALUEID INT
)

-- Fill table #PMSTATUSFILTERTABLE
INSERT
INTO #PMSTATUSFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@PMSTATUS, N'') AS p

-- Filter table for SubnetC values
CREATE TABLE #SUBNETCFILTERTABLE
(
IPID INT,
SUBNETC NVARCHAR(50) COLLATE database_default
)

-- Insert into filter id of the SubnetC to increase performence for event table
INSERT INTO #SUBNETCFILTERTABLE
SELECT DISTINCT
ipid,
ip.SubNetC
FROM
APM.IP AS ip (NOLOCK)
JOIN APM.GetMultiParameters(CASE WHEN LEN(@INCLUDESUBNET) &gt; 0 THEN @INCLUDESUBNET ELSE N'%' END, N'') AS p1 ON (ip.SubnetC LIKE p1.Value)
LEFT OUTER JOIN APM.GetMultiParameters(CASE WHEN LEN(@EXCLUDESUBNET) &gt; 0 THEN @EXCLUDESUBNET ELSE N'Fake' END, N'') AS p2 ON (ip.SubnetC LIKE p2.Value)
WHERE
--Exclude subnets which have correspondance in @EXCLUDESUBNET parameter
p2.typeId IS NULL

CREATE TABLE #CLIENTEVENT
(
CSEVENTID INT,
SOURCEID INT
)

INSERT INTO #CLIENTEVENT
SELECT
e.CSEventId,
e.SourceId
FROM
APM.CSEvent (NOLOCK) AS e
JOIN #SOURCEMACHINEFILTERTABLE AS f1 ON (f1.VALUEID = e.SourceId AND f1.TYPEID = 1)
JOIN #SOURCEMACHINEFILTERTABLE AS f2 ON (f2.VALUEID = e.MachineId AND f2.TYPEID = 2)
JOIN #SUBNETCFILTERTABLE AS f3 ON e.ipid = f3.IPID
JOIN #PMSTATUSFILTERTABLE AS f4 ON (f4.VALUEID = e.PMStatus)
WHERE
e.ClassType = N'Performance'
AND e.UTCDate &gt;= @STARTDATE
AND e.UTCDate &lt; @ENDDATE

CREATE TABLE #LATENCIES
(
ID INT,
MIN INT,
MAX INT
)

INSERT INTO #LATENCIES VALUES (1, 0, 100)
INSERT INTO #LATENCIES VALUES (2, 101, 300)
INSERT INTO #LATENCIES VALUES (3, 301, 600)
INSERT INTO #LATENCIES VALUES (4, 601, 1000)
INSERT INTO #LATENCIES VALUES (5, 1001, 2000)
INSERT INTO #LATENCIES VALUES (6, 2001, 99999999)

;WITH AJAXEvents AS
(
SELECT
e.CSEVENTID,
e.SOURCEID,
ajax.TotalTime AS TotalTime,
ajax.Latency AS Latency
FROM
#CLIENTEVENT AS e
JOIN APM.CSAJAX AS ajax (NOLOCK) ON e.CSEVENTID = ajax.CSEventId
),
JSEvents AS
(
SELECT
e.CSEVENTID,
e.SOURCEID,
js.TotalTime AS TotalTime,
NULL AS Latency
FROM
#CLIENTEVENT AS e
JOIN APM.CSJSCRIPTEVENT AS js (NOLOCK) ON e.CSEVENTID = js.CSEventId

),
PageEvents AS
(
SELECT
e.CSEVENTID,
e.SOURCEID,
p.TotalTime AS TotalTime,
p.Latency AS Latency
FROM
#CLIENTEVENT AS e
JOIN APM.CSPAGEEVENT AS p (NOLOCK) ON e.CSEVENTID = p.CSEventId
),
UnionEvents AS
(
SELECT * from AJAXEvents
UNION ALL
SELECT * from JSEvents
UNION ALL
SELECT * from PageEvents
),
EventAggregation AS
(
SELECT
SourceId,
MAX(TotalTime) / 1000.0 AS TotalTime,
AVG(Latency) AS Latency
FROM UnionEvents
GROUP BY
CSEventId, SourceId
),
NumberedDataSet AS
(
SELECT
ROW_NUMBER() OVER(ORDER BY COUNT(CASE
WHEN @ORDERBY = 1 AND L.ID = 1 THEN 1
WHEN @ORDERBY = 2 AND L.ID = 2 THEN 1
WHEN @ORDERBY = 3 AND L.ID = 3 THEN 1
WHEN @ORDERBY = 4 AND L.ID = 4 THEN 1
WHEN @ORDERBY = 5 AND L.ID = 5 THEN 1
WHEN @ORDERBY = 6 THEN 1
END) DESC) AS Id,
SourceId,
COUNT(CASE WHEN L.ID = 1 THEN 1 END) AS EventCount1,
COUNT(CASE WHEN L.ID = 2 THEN 1 END) AS EventCount2,
COUNT(CASE WHEN L.ID = 3 THEN 1 END) AS EventCount3,
COUNT(CASE WHEN L.ID = 4 THEN 1 END) AS EventCount4,
COUNT(CASE WHEN L.ID = 5 THEN 1 END) AS EventCount5,
COUNT(CASE WHEN L.ID = 6 THEN 1 END) AS EventCount6,
AVG(CASE WHEN L.ID = 1 THEN TotalTime END) AS EventDuration1,
AVG(CASE WHEN L.ID = 2 THEN TotalTime END) AS EventDuration2,
AVG(CASE WHEN L.ID = 3 THEN TotalTime END) AS EventDuration3,
AVG(CASE WHEN L.ID = 4 THEN TotalTime END) AS EventDuration4,
AVG(CASE WHEN L.ID = 5 THEN TotalTime END) AS EventDuration5,
COUNT(*) AS EventCount
FROM EventAggregation AS EA
JOIN #LATENCIES AS L ON COALESCE(EA.Latency, 99999999) &gt;= L.MIN AND COALESCE(EA.Latency, 99999999) &lt;= L.MAX
GROUP BY SourceId
)
--Select each range info into separate row to provide better view in report charts
SELECT
sr.Id,
r.n AS LatencyRange,
sr.EventCount,
s.Source,
sr.SourceId,
(CASE WHEN r.n = 1 THEN sr.EventCount1 END) AS EventCount1,
(CASE WHEN r.n = 2 THEN sr.EventCount2 END) AS EventCount2,
(CASE WHEN r.n = 3 THEN sr.EventCount3 END) AS EventCount3,
(CASE WHEN r.n = 4 THEN sr.EventCount4 END) AS EventCount4,
(CASE WHEN r.n = 5 THEN sr.EventCount5 END) AS EventCount5,
(CASE WHEN r.n = 1 THEN COALESCE(sr.EventDuration1, 0) END) AS EventDuration1,
(CASE WHEN r.n = 2 THEN COALESCE(sr.EventDuration2, 0) END) AS EventDuration2,
(CASE WHEN r.n = 3 THEN COALESCE(sr.EventDuration3, 0) END) AS EventDuration3,
(CASE WHEN r.n = 4 THEN COALESCE(sr.EventDuration4, 0) END) AS EventDuration4,
(CASE WHEN r.n = 5 THEN COALESCE(sr.EventDuration5, 0) END) AS EventDuration5
FROM
NumberedDataSet AS sr
JOIN APM.Source AS s (NOLOCK) ON sr.SourceId = s.SourceId,
APM.fn_nums(5) AS r
ORDER BY
sr.Id,
r.n
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.ClientLatencyDistributionSubReport'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.ClientLatencyDistributionSubReport AS RETURN 1')
END
GO

/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME:ClientLatencyDistributionSubReport */
/* USED IN: Client Latency Distribution for sub report */
/* INPUT PARAMETERS: */
/* @STARTDATE - Start date of the priod */
/* @ENDDATE - End date of the period */
/* @SOURCEID - Id of the source */
/* @MACHINEIDS - List of machine Id, separated by comma. Exp: '4,5,6' */
/* @SUBNETC - List subnet type C, selected by user */
/* @ORDERBY - Specifies field to which sorting should be applayed */
/* 1. Event Count */
/* 2. Problems Count */
/* 4. Event Duration */
/* 5. Latency */
/************************************************************************************/
ALTER PROCEDURE APM.ClientLatencyDistributionSubReport
@STARTDATE DATETIME,
@ENDDATE DATETIME,
@SOURCEID INT,
@MACHINEIDS NVARCHAR(MAX),
@INCLUDESUBNET NVARCHAR(MAX),
@EXCLUDESUBNET NVARCHAR(MAX),
@ORDERBY INT,
@PMSTATUS NVARCHAR(50)
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON

/****************************************************************************************/
/* ASSISTING TEMP TABLES */
/****************************************************************************************/

SELECT
@INCLUDESUBNET = REPLACE(@INCLUDESUBNET, N'*', N'%'),
@EXCLUDESUBNET = REPLACE(@EXCLUDESUBNET, N'*', N'%')

-- Filter table, which contains machine ids and source ids
-- valueId filter value for machine id
CREATE TABLE #MACHINEFILTERTABLE(
VALUEID INT
)

INSERT
INTO #MACHINEFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@MACHINEIDS, N'') AS p

-- Filter table, which contains PM Statuses of Events
CREATE TABLE #PMSTATUSFILTERTABLE(
VALUEID INT
)

-- Fill table #PMSTATUSFILTERTABLE
INSERT
INTO #PMSTATUSFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@PMSTATUS, N'') AS p

-- Filter table for SubnetC values
CREATE TABLE #SUBNETCFILTERTABLE
(
IPID INT,
SUBNETC NVARCHAR(50) COLLATE database_default
)

-- Insert into filter id of the SubnetC to increase performence for event table
INSERT INTO #SUBNETCFILTERTABLE
SELECT
ipid,
ip.SubNetC
FROM
APM.IP AS ip (NOLOCK)
JOIN APM.GetMultiParameters(CASE WHEN LEN(@INCLUDESUBNET) &gt; 0 THEN @INCLUDESUBNET ELSE N'%' END, N'') AS p1 ON (ip.SubnetC LIKE p1.Value)
LEFT OUTER JOIN APM.GetMultiParameters(CASE WHEN LEN(@EXCLUDESUBNET) &gt; 0 THEN @EXCLUDESUBNET ELSE N'Fake' END, N'') AS p2 ON (ip.SubnetC LIKE p2.Value)
WHERE
--Exclude subnets which have correspondance in @EXCLUDESUBNET parameter
p2.typeId IS NULL

CREATE TABLE #CLIENTEVENT
(
CSEVENTID INT,
CSEVENTGROUPID INT,
SUBNETC NVARCHAR(50) collate database_default
)

INSERT INTO #CLIENTEVENT
SELECT
e.CSEventId,
e.CSEventGroupId,
f3.SUBNETC
FROM
APM.CSEvent (NOLOCK) AS e
JOIN #MACHINEFILTERTABLE AS f1 ON f1.VALUEID = e.MachineId
JOIN #PMSTATUSFILTERTABLE AS f2 ON (f2.VALUEID = e.PMStatus)
JOIN #SUBNETCFILTERTABLE AS f3 ON e.ipid = f3.IPID
WHERE
e.ClassType = N'Performance'
AND e.SourceId = @SOURCEID
AND e.UTCDate &gt;= @STARTDATE
AND e.UTCDate &lt; @ENDDATE

/****************************************************************************************/
/* MAIN QUERY */
/****************************************************************************************/
-- Aggregate AJAX by event id, as several synchronous ajax call can belong to one event
;WITH AJAXEvents AS
(
SELECT
e.CSEVENTID,
-- Aggregation by Total Time make no difference, as for synch ajaxes total time will
-- be taken from JS event, and for asynch AJAX here can be only one row
AVG(ajax.TotalTime) AS TotalTime,
-- For synch ajax select average latency among calls, for asynch here will be only one row
AVG(ajax.Latency) AS Latency
FROM
#CLIENTEVENT AS e
JOIN APM.CSAJAX AS ajax (NOLOCK) ON e.CSEVENTID = ajax.CSEventId
GROUP BY
e.CSEVENTID
),
-- For each subnet choose its average latency and event duration
SubNetCStatistics AS
(
SELECT
e.SUBNETC,
COUNT(e.CSEVENTID) AS EventCount,
COUNT(DISTINCT e.CSEVENTGROUPID) AS ProblemCount,
-- Event could by either Page or JavaScript or Asycnh Ajax. Row in AJAX table will be presented for both synch and asynch ajaxes,
-- But for synch AJAXes only latency should by taken and Total Time should by taken from either Page event or Jscript event
AVG(COALESCE(p.TotalTime, COALESCE(js.TotalTime, ajax.TotalTime)))/1000.0 AS EventDuration,
--Latency could be either in page event or in Ajax event
AVG(COALESCE(p.Latency, ajax.Latency)) AS Latency
FROM
#CLIENTEVENT AS e
LEFT OUTER JOIN AJAXEvents AS ajax ON ajax.CSEventId = e.CSEVENTID
LEFT OUTER JOIN APM.CSPageEvent AS p (NOLOCK) ON p.CSEventId = e.CSEVENTID
LEFT OUTER JOIN APM.CSJScriptEvent AS js (NOLOCK) ON e.CSEVENTID = js.CSEventId
GROUP BY
e.SUBNETC
)
-- Select top 5 rows, ordered by specified parameter @ORDERBY
SELECT TOP(5)
ROW_NUMBER() OVER(ORDER BY (CASE @ORDERBY
WHEN 1 THEN EventCount
WHEN 2 THEN ProblemCount
WHEN 3 THEN EventDuration
WHEN 4 THEN Latency
END) DESC) AS Id,
SubNetC AS Client,
EventCount,
ProblemCount,
EventDuration,
Latency
FROM
SubNetCStatistics
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.ApplicationAnalysisJScriptWithAjaxCalls'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.ApplicationAnalysisJScriptWithAjaxCalls AS RETURN 1')
END
GO

/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: ApplicationAnalysisJScriptWithAjaxCalls */
/* USED IN: Application Analysis report for TOP slowest Ajax, top slowest JS, */
/* TOP largest AJAX */
/* INPUT PARAMETERS: */
/* @STARTDATE - Start date of the priod */
/* @ENDDATE - End date of the period */
/* @SOURCEID - SourceId */
/* @MACHINEIDS - List of machine Id, separated by comma. Exp: '4,5,6' */
/* @INCLUDESUBNET - List masks, which should be included */
/* @EXCLUDESUBNET - List masks, which should be excluded */
/* @THRESHOLD - Event threshold */
/* @ORDERBY1 - Specifies field to which sorting for largest AJAX calls */
/* should be applayed. Possible Values: */
/* 1. Event Count */
/* 2. Request Size */
/* 3. Response Size */
/* 4. Total Size */
/* 5. Total Time */
/* @ORDERBY2 - Specifies field to which sorting for slowest AJAX calls */
/* should be applayed. Possible Values: */
/* 1. Event Count */
/* 2. Client Time */
/* 3. Network Time */
/* 4. Server Time */
/* 5. Total Time */
/* 6. Request Size */
/* 7. Response Size */
/* 8. Latency */
/* @ORDERBY3 - Specifies field to which sorting for slowest JavaScript */
/* should be applayed. Possible Values: */
/* 1. Event Count */
/* 2. AJAX Call Count */
/* 3. Client Time */
/* 4. Network Time */
/* 5. Server Time */
/* 6. Total Time */
/* 7. Avg Event Size */
/* 8. Latency */
/************************************************************************************/
ALTER PROCEDURE APM.ApplicationAnalysisJScriptWithAjaxCalls
@STARTDATE DATETIME,
@ENDDATE DATETIME,
@SOURCEID NVARCHAR(MAX),
@MACHINEIDS NVARCHAR(MAX),
@INCLUDESUBNET NVARCHAR(MAX),
@EXCLUDESUBNET NVARCHAR(MAX),
@PMSTATUS NVARCHAR(50),
@ORDERBY1 INT,
@ORDERBY2 INT,
@ORDERBY3 INT
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON

/****************************************************************************************/
/* ASSISTING TEMP TABLES */
/****************************************************************************************/

SELECT
@INCLUDESUBNET = REPLACE(@INCLUDESUBNET, N'*', N'%'),
@EXCLUDESUBNET = REPLACE(@EXCLUDESUBNET, N'*', N'%')

-- Filter table, which contains machine ids and source ids
-- valueId filter value - machine id
CREATE TABLE #MACHINEFILTERTABLE(
VALUEID INT
)

-- Fill table #SOURCEMACHINEFILTERTABLE
INSERT
INTO #MACHINEFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@MACHINEIDS, N'') AS p

-- Filter table, which contains PM Statuses of Events
CREATE TABLE #PMSTATUSFILTERTABLE(
VALUEID INT
)

-- Fill table #PMSTATUSFILTERTABLE
INSERT
INTO #PMSTATUSFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@PMSTATUS, N'') AS p

-- Filter table for SubnetC values
CREATE TABLE #SUBNETCFILTERTABLE
(
IPID INT,
SUBNETC NVARCHAR(50) collate database_default
)

-- Insert into filter id of the SubnetC to increase performance for event table
INSERT INTO #SUBNETCFILTERTABLE
SELECT DISTINCT
ipid,
SubNetC
FROM
IP AS ip (NOLOCK)
JOIN APM.GetMultiParameters(CASE WHEN LEN(@INCLUDESUBNET) &gt; 0 THEN @INCLUDESUBNET ELSE N'%' END, N'') AS p1 ON (ip.SubnetC LIKE p1.Value)
LEFT OUTER JOIN APM.GetMultiParameters(CASE WHEN LEN(@EXCLUDESUBNET) &gt; 0 THEN @EXCLUDESUBNET ELSE N'Fake' END, N'') AS p2 ON (ip.SubnetC LIKE p2.Value)
WHERE
--Exclude subnets which have correspondance in @EXCLUDESUBNET parameter
p2.typeId IS NULL

CREATE TABLE #CLIENTEVENTS
(
CSEVENTID INT,
PAGEURI NVARCHAR(255) COLLATE database_default,
CLASSTYPE NVARCHAR(50) COLLATE database_default,
CSEVENTGROUPID INT
)

INSERT INTO #CLIENTEVENTS
SELECT
e.CSEventId,
e.PageUri,
e.ClassType,
e.CSEventGroupId
FROM
APM.CSEvent (NOLOCK) AS e
JOIN #MACHINEFILTERTABLE AS f ON (f.VALUEID = e.MachineId)
JOIN #SUBNETCFILTERTABLE AS f2 ON e.ipid = f2.IPID
JOIN #PMSTATUSFILTERTABLE AS f3 ON (f3.VALUEID = e.PMStatus)
WHERE
e.sourceId = @SOURCEID
AND PageUri IS NOT NULL
AND e.UTCDate &gt;= @STARTDATE
AND e.UTCDate &lt; @ENDDATE
AND e.EventClass &lt;&gt; N'CSMPMonitorLog'

CREATE TABLE #AJAXCALLS
(
ID INT,
CSEVENTID INT,
PAGEURI NVARCHAR(255) COLLATE database_default,
AJAXACTION NVARCHAR(255) COLLATE database_default,
TOTALTIME DECIMAL(35, 0),
NETWORKTIME DECIMAL(35, 0),
SERVERTIME DECIMAL(35, 0),
RESPONSETIME DECIMAL(35, 0),
REQUESTSIZE DECIMAL(35, 0),
RESPONSESIZE DECIMAL(35, 0),
LATENCY BIGINT,
TOTALAJAXCALLCOUNT INT,
AVGAJAXCALLDURATION FLOAT,
SYNCHRONOUS BIT
)
-- Several synchronous Ajax calls could belong to one event, in that case only heaviest (by Total duration) should be taken.
-- Numerate Ajax calls for each event by Total Time in descending order.
-- Next step is to take ajax calls with id equal to 1.
-- For asynch ajaxes all rows will be with id = 1
;WITH AjaxCallsInternal AS
(
SELECT
ROW_NUMBER() OVER(PARTITION BY E.CSEVENTID ORDER BY ajax.TOTALTIME DESC, ajax.CSAJAXId) AS Id,
e.CSEVENTID,
e.PAGEURI,
ajax.URI,
COALESCE(ajax.TOTALTIME, 0) AS TotalTime,
COALESCE(ajax.NETWORKTIME, 0) AS NetworkTime,
COALESCE(ajax.SERVERTIME, 0) AS ServerTime,
COALESCE(ajax.RESPONSETIME, 0) AS ResponseTime,
COALESCE(ajax.REQUESTSIZE, 0) AS RequestSize,
COALESCE(ajax.RESPONSESIZE, 0) AS ResponseSize,
ajax.LATENCY,
COUNT(CSAJAXId) OVER(PARTITION BY e.CSEVENTID) AS TotalAjaxCallCount,
ajax.SYNCHRONOUS
FROM
APM.CSAJAX AS ajax (NOLOCK)
JOIN #CLIENTEVENTS AS e ON e.CSEVENTID = ajax.CSEVENTID
),
AjaxCallsWithAvg AS
(
SELECT
Id,
CSEVENTID,
PAGEURI,
URI,
TotalTime,
NetworkTime,
ServerTime,
ResponseTime,
RequestSize,
ResponseSize,
LATENCY,
TotalAjaxCallCount,
--calculate avg only for haviest ajax calls by ms
AVG(CASE Id WHEN 1 THEN TotalTime END) OVER() AS AvgAjaxCallDuration,
SYNCHRONOUS
FROM
AjaxCallsInternal
)
INSERT INTO #AJAXCALLS
SELECT * FROM AjaxCallsWithAvg

/****************************************************************************************/
/* MAIN QUERY */
/****************************************************************************************/
--Group information over ajax calls
;WITH HeaviestAjaxCalls AS
(
SELECT
PAGEURI,
AJAXACTION,
SYNCHRONOUS,
COUNT(CSEVENTID) AS EventCount,
AVG(TOTALTIME)/1000.0 AS TotalTime,
AVG(NETWORKTIME)/1000.0 AS NetworkTime,
AVG(SERVERTIME)/1000.0 AS ServerTime,
AVG(RESPONSETIME)/1000.0 AS ResponseTime,
AVG(REQUESTSIZE)/1024.0 AS RequestSize,
AVG(RESPONSESIZE)/1024.0 AS ResponseSize,
AVG(LATENCY) AS Latency,
MAX(REQUESTSIZE + RESPONSESIZE)/1024.0 AS MaxAjaxCall,
MAX(TOTALTIME)/1000.0 AS MaxAjaxCallDuration,
SUM(TOTALAJAXCALLCOUNT) AS TotalAjaxCallCount,
MIN(AVGAJAXCALLDURATION) / 1000.0 AS AvgAjaxCallDuration
FROM
#AJAXCALLS
WHERE
--Select only heaviest AJAX calls for each event
ID = 1
GROUP BY
PAGEURI,
AJAXACTION,
SYNCHRONOUS
),
-- Select information for top 10 Largest AJAX calls
LargestAjaxCalls AS
(
SELECT
ROW_NUMBER() OVER (ORDER BY CASE @ORDERBY1
WHEN 1 THEN EventCount
WHEN 2 THEN RequestSize
WHEN 3 THEN ResponseSize
WHEN 4 THEN COALESCE(RequestSize, 0) + COALESCE(ResponseSize, 0)
WHEN 5 THEN TotalTime
END DESC) AS Id,
PageUri,
AjaxAction,
EventCount,
RequestSize,
ResponseSize,
TotalTime,
TotalAjaxCallCount,
SUM(EventCount) OVER() AS TotalAjaxEventCount,
AVG(RequestSize + ResponseSize) OVER() AS AvgAjaxCallSize,
MAX(MaxAjaxCall) OVER() AS LargestAjaxCallSize
FROM
HeaviestAjaxCalls AS h
),
--Select information for top Slowest Ajax Calls (only asynch AJAXes)
SlowestAjaxCalls AS
(
SELECT
ROW_NUMBER() OVER (ORDER BY CASE @ORDERBY2
WHEN 1 THEN EventCount
WHEN 2 THEN TotalTime - (NetworkTime + ResponseTime + ServerTime)
WHEN 3 THEN NetworkTime + ResponseTime
WHEN 4 THEN ServerTime
WHEN 5 THEN TotalTime
WHEN 6 THEN RequestSize
WHEN 7 THEN ResponseSize
WHEN 8 THEN Latency
END DESC) AS Id,
PageUri,
AjaxAction,
EventCount,
NetworkTime + ResponseTime AS NetworkTime,
ServerTime,
TotalTime - (NetworkTime + ResponseTime + ServerTime) AS ClientTime,
TotalTime,
RequestSize,
ResponseSize,
Latency,
SUM(EventCount) OVER() AS TotalAjaxEventCount,
AvgAjaxCallDuration,
MAX(MaxAjaxCallDuration) OVER() AS MaxAjaxCallDuration
FROM
HeaviestAjaxCalls AS h
WHERE
-- Select only Asynch AJAXes
Synchronous = 0
),
JavaScriptActions AS
(
SELECT
js.ACTION,
e.PAGEURI,
COUNT(e.CSEVENTID) AS EventCount,
SUM(COALESCE(ajax.TOTALAJAXCALLCOUNT, 0)) AS AjaxCallCount,
AVG(COALESCE(ajax.NETWORKTIME + ajax.RESPONSETIME, 0))/1000.0 AS JSNetworkTime,
AVG(COALESCE(ajax.SERVERTIME, 0))/1000.0 AS JSServerTime,
-- Clinet time is calculated as jsevent time minus ajax call time
-- If JavaScript function has no ajax calls, then all time consider to be client time
AVG(js.TOTALTIME - COALESCE(ajax.TOTALTIME, 0))/1000.0 AS JSClientTime,
AVG(js.TOTALTIME)/1000.0 AS JSTotalTime,
AVG(REQUESTSIZE + RESPONSESIZE)/1024.0 AS AvgSize,
AVG(LATENCY) AS Latency,
MAX(js.TOTALTIME)/1000.0 AS JSMaxTime
FROM
APM.CSJScriptEvent AS js (NOLOCK)
JOIN #CLIENTEVENTS AS e ON e.CSEVENTID = js.CSEVENTID
-- If Java script has ajax events, condition id = 1 alows to select largest (by total time) ajax call
LEFT OUTER JOIN #AJAXCALLS AS ajax ON (ajax.ID = 1 AND ajax.CSEVENTID = js.CSEVENTID)
GROUP BY
js.ACTION,
e.PAGEURI
),
-- Order java script info by specified parameter
SlowestJScript AS
(
SELECT
ROW_NUMBER() OVER(ORDER BY (CASE @ORDERBY3
WHEN 1 THEN EventCount
WHEN 2 THEN AJAXCallCount
WHEN 3 THEN JSClientTime
WHEN 4 THEN JSNetworkTime
WHEN 5 THEN JSServerTime
WHEN 6 THEN JSTotalTime
WHEN 7 THEN AvgSize
WHEN 8 THEN Latency
END) DESC) AS id,
Action AS JSAction,
PageUri,
EventCount,
AJAXCallCount,
JSClientTime,
JSNetworkTime,
JSServerTime,
JSTotalTime,
AvgSize,
Latency,
SUM(EventCount) OVER() AS TotalJSEventCount,
MAX(JSMaxTime) OVER() AS JScriptMaxTime,
-- Calculate average time for all java script events
(SUM(JSTotalTime*EventCount) OVER())/(SUM(EventCount) OVER()) AS AverageJScriptTime
FROM
JavaScriptActions
)
--select TOP 10 rows from each query
SELECT
[top].n AS Id,
-- Largest Ajax Calls
la.PageUri AS la_PageUri,
la.AjaxAction AS la_AjaxAction,
la.EventCount AS la_EventCount,
la.RequestSize AS la_RequestSize,
la.ResponseSize AS la_ResponseSize,
la.TotalTime AS la_TotalTime,
-- End Largest Ajax Calls
-- Slowest AJAX Calls
sa.PageUri AS sa_PageUri,
sa.AjaxAction AS sa_AjaxAction,
sa.EventCount AS sa_EventCount,
sa.NetworkTime AS sa_NetworkTime,
sa.ServerTime AS sa_ServerTime,
sa.ClientTime AS sa_ClientTime,
sa.TotalTime AS sa_TotalTime,
sa.RequestSize AS sa_RequestSize,
sa.ResponseSize AS sa_ResponseSize,
sa.Latency AS sa_Latency,
sa.TotalAjaxEventCount AS sa_TotalAsynchAjaxesCount,
-- End Slowest AJAX Calls
-- Slowest JavaScript
js.JSAction AS js_Action,
js.PageUri AS js_PageUri,
js.EventCount AS js_EventCount,
js.AJAXCallCount AS js_AJAXCallCount,
js.JSClientTime AS js_JSClientTime,
js.JSNetworkTime AS js_JSNetworkTime,
js.JSServerTime AS js_JSServerTime,
js.JSTotalTime AS js_JSTotalTime,
js.AvgSize AS js_AvgSize,
js.Latency AS js_Latency,
js.TotalJSEventCount,
-- End Slowest JavaScript
-- Summary information
la.TotalAjaxCallCount,
la.TotalAjaxEventCount,
la.AvgAjaxCallSize,
la.LargestAjaxCallSize,
sa.AvgAjaxCallDuration,
sa.MaxAjaxCallDuration,
js.JScriptMaxTime,
js.AverageJScriptTime
-- End Summary Information
FROM
APM.fn_nums(10) AS [top]
LEFT OUTER JOIN LargestAjaxCalls AS la ON [top].n = la.Id
LEFT OUTER JOIN SlowestAjaxCalls AS sa ON [top].n = sa.Id
LEFT OUTER JOIN SlowestJScript AS js ON [top].n = js.Id
ORDER BY
Id
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.ApplicationAnalysisTopPages'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.ApplicationAnalysisTopPages AS RETURN 1')
END
GO

/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: ApplicationAnalysisTopPages */
/* USED IN: Application Analysis report for TOP 10 slowest ans top 10 largest pages */
/* INPUT PARAMETERS: */
/* @STARTDATE - Start date of the priod */
/* @ENDDATE - End date of the period */
/* @SOURCEID - SourceId */
/* @MACHINEIDS - List of machine Id, separated by comma. Exp: '4,5,6' */
/* @INCLUDESUBNET - Subnet masks list, which should be included */
/* @EXCLUDESUBNET - Subnet masks list, which should be excluded */
/* @ORDERBY1 - Specifies field to which sorting for largest pages */
/* should be applayed. Possible Values: */
/* 1. Event Count */
/* 2. Image Size */
/* 3. CSS Size */
/* 4. HTC Behavior Size */
/* 5. Script Size */
/* 6. HTML Size */
/* 7. AJAX Size */
/* 8. Avg Page Size */
/* 9. Event Duration Time */
/* @ORDERBY2 - Specifies field to which sorting for slowest pages */
/* should be applayed. Possible Values: */
/* 1. Event Count */
/* 2. Network Time */
/* 3. Server Time */
/* 4. DOM Time */
/* 5. Peripheral Time */
/* 6. OnLoad Time */
/* 7. Event Duration */
/************************************************************************************/
ALTER PROCEDURE APM.ApplicationAnalysisTopPages
@STARTDATE DATETIME,
@ENDDATE DATETIME,
@SOURCEID NVARCHAR(MAX),
@MACHINEIDS NVARCHAR(MAX),
@INCLUDESUBNET NVARCHAR(MAX),
@EXCLUDESUBNET NVARCHAR(MAX),
@PMSTATUS NVARCHAR(50),
@ORDERBY1 INT,
@ORDERBY2 INT
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON

/****************************************************************************************/
/* ASSISTING TEMP TABLES */
/****************************************************************************************/
SELECT
@INCLUDESUBNET = REPLACE(@INCLUDESUBNET, N'*', N'%'),
@EXCLUDESUBNET = REPLACE(@EXCLUDESUBNET, N'*', N'%')

-- Filter table, which contains machine ids and source ids
-- valueId filter value - machine id
CREATE TABLE #MACHINEFILTERTABLE(
VALUEID INT
)

-- Fill table #SOURCEMACHINEFILTERTABLE
INSERT
INTO #MACHINEFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@MACHINEIDS, N'') AS p

-- Filter table, which contains PM Statuses of Events
CREATE TABLE #PMSTATUSFILTERTABLE(
VALUEID INT
)

-- Fill table #PMSTATUSFILTERTABLE
INSERT
INTO #PMSTATUSFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@PMSTATUS, N'') AS p

-- Filter table for SubnetC values
CREATE TABLE #SUBNETCFILTERTABLE
(
IPID INT,
SUBNETC NVARCHAR(50) COLLATE DATABASE_DEFAULT
)

-- Insert into filter id of the SubnetC to increase performance for event table
INSERT INTO #SUBNETCFILTERTABLE
SELECT DISTINCT
ipid,
SubNetC
FROM
APM.IP AS ip (NOLOCK)
JOIN APM.GetMultiParameters(CASE WHEN LEN(@INCLUDESUBNET) &gt; 0 THEN @INCLUDESUBNET ELSE N'%' END, N'') AS p1 ON (ip.SubnetC LIKE p1.Value)
LEFT OUTER JOIN APM.GetMultiParameters(CASE WHEN LEN(@EXCLUDESUBNET) &gt; 0 THEN @EXCLUDESUBNET ELSE N'Fake' END, N'') AS p2 ON (ip.SubnetC LIKE p2.Value)
WHERE
--Exclude subnets which have correspondance in @EXCLUDESUBNET parameter
p2.typeId IS NULL

CREATE TABLE #CLIENTEVENTS
(
CSEVENTID INT,
PAGEURI NVARCHAR(255) COLLATE DATABASE_DEFAULT,
CLASSTYPE NVARCHAR(50) COLLATE DATABASE_DEFAULT,
CSEVENTGROUPID INT
)

INSERT INTO #CLIENTEVENTS
SELECT
e.CSEVENTID,
e.PAGEURI,
e.CLASSTYPE,
e.CSEVENTGROUPID
FROM
APM.CSEvent (NOLOCK) AS e
JOIN #MACHINEFILTERTABLE AS f ON (f.VALUEID = e.MACHINEID)
JOIN #SUBNETCFILTERTABLE AS f2 ON e.ipid = f2.IPID
JOIN #PMSTATUSFILTERTABLE AS f3 ON (f3.VALUEID = e.PMSTATUS)
WHERE
e.SOURCEID = @SOURCEID
AND e.PAGEURI IS NOT NULL
AND e.UTCDATE &gt;= @STARTDATE
AND e.UTCDATE &lt; @ENDDATE
AND e.EVENTCLASS = N'CSMPMonitorLog'

/****************************************************************************************/
/* MAIN QUERY */
/****************************************************************************************/
;WITH AjaxCalls AS
(
SELECT
e.CSEVENTID,
SUM(ajax.RESPONSESIZE) AS ResponseSize,
SUM(ajax.REQUESTSIZE) AS RequestSize
FROM
APM.CSAJAX AS ajax (NOLOCK)
JOIN #CLIENTEVENTS AS e ON e.CSEVENTID = ajax.CSEventId
GROUP BY
e.CSEVENTID
),
-- Select information about page content size for each event (this information is available only for page events)
PeripheralDetails AS
(
SELECT
b.CSEventId,
COALESCE(b.Image, 0) AS Image,
COALESCE(b.HtcBehavior, 0) AS HtcBehavior,
COALESCE(b.Script, 0) AS Script,
COALESCE(b.html, 0) AS html,
COALESCE(b.CssStyle, 0) AS CssStyle,
COALESCE(ajax.ResponseSize + ajax.REQUESTSIZE, 0) AS Ajax,
COALESCE(b.Image, 0) + COALESCE(b.HtcBehavior, 0) + COALESCE(b.Script, 0)
+ COALESCE(b.html, 0) + COALESCE(b.CssStyle, 0)
+ COALESCE(ajax.ResponseSize + ajax.REQUESTSIZE, 0) AS TotalSize
FROM
(
SELECT
e.CSEVENTID,
p.TYPE,
p.TOTALSIZE
FROM
#CLIENTEVENTS AS e
JOIN APM.CSPeripheral AS p (NOLOCK) ON e.CSEVENTID = p.CSEVENTID
)AS A
PIVOT (SUM(TotalSize) FOR Type IN (Image, HtcBehavior, Script, html, CssStyle)) AS b
LEFT OUTER JOIN AjaxCalls AS ajax ON (ajax.CSEVENTID = b.CSEVENTID)
),
-- Group page events information by pages
PageEvents AS
(
SELECT
e.PAGEURI,
COUNT(e.CSEVENTID) AS EventCount,
-- All null values in time segments should be changed to 0, to provide convergence with average total time
AVG(COALESCE(p.NetworkTime, 0))/1000.0 AS NetworkTime,
AVG(COALESCE(p.ServerTime, 0))/1000.0 AS ServerTime,
AVG(COALESCE(p.DomTime, 0))/1000.0 AS DomTime,
AVG(COALESCE(p.PeripheralTime, 0))/1000.0 AS PeripheralTime,
AVG(COALESCE(p.OnLoadTime, 0))/1000.0 AS OnLoadTime,
AVG(p.TotalTime)/1000.0 AS EventDuration,
MAX(p.TotalTime)/1000.0 AS MaxEventDuration,
AVG(d.TotalSize)/1024.0 AS AveragePageSize,
MAX(d.TotalSize)/1024.0 AS MaxPageSize,
AVG(d.Image)/1024.0 AS ImageSize,
AVG(d.HtcBehavior)/1024.0 AS HtcBehaviorSize,
AVG(d.Script)/1024.0 AS ScriptSize,
AVG(d.html)/1024.0 AS HTMLSize,
AVG(d.CssStyle)/1024.0 AS CssStyleSize,
AVG(Ajax)/1024.0 AS AJAXCallSize
FROM
#CLIENTEVENTS AS e
JOIN APM.CSPageEvent AS p (NOLOCK) ON p.CSEventId = e.CSEVENTID
LEFT OUTER JOIN PeripheralDetails AS d ON d.CSEventId = e.CSEVENTID
GROUP BY
e.PAGEURI
),
-- Select information for top 10 largest pages
LargesPage AS
(
SELECT
ROW_NUMBER() OVER(ORDER BY (CASE @ORDERBY1
WHEN 1 THEN EventCount
WHEN 2 THEN ImageSize
WHEN 3 THEN CssStyleSize
WHEN 4 THEN HtcBehaviorSize
WHEN 5 THEN ScriptSize
WHEN 6 THEN HTMLSize
WHEN 7 THEN AJAXCallSize
WHEN 8 THEN AveragePageSize
WHEN 9 THEN EventDuration
END) DESC) AS id,
PageUri,
EventCount,
ImageSize,
CssStyleSize,
HtcBehaviorSize,
ScriptSize,
HTMLSize,
AJAXCallSize,
AveragePageSize AS TotalSize,
EventDuration,
SUM(EventCount) OVER() AS TotalPageEventCount,
-- Select information about max page size and average page size over all application events,
-- This information will be shown in report summary information
MAX(MaxPageSize) OVER() AS MaxPageSize,
(SUM(AveragePageSize*EventCount) OVER())/(SUM(EventCount) OVER()) AS AveragePageSize
FROM
PageEvents
),
-- Select information for top 10 slowest pages
SlowestPage AS
(
SELECT
ROW_NUMBER() OVER(ORDER BY (CASE @ORDERBY2
WHEN 1 THEN EventCount
WHEN 2 THEN NetworkTime
WHEN 3 THEN ServerTime
WHEN 4 THEN DomTime
WHEN 5 THEN PeripheralTime
WHEN 6 THEN OnLoadTime
WHEN 7 THEN EventDuration
END) DESC) AS id,
PageUri,
EventCount,
NetworkTime,
ServerTime,
DomTime,
PeripheralTime,
OnLoadTime,
EventDuration AS TotalTime,
-- Select information about max page load time and average page load time over all application events,
-- This information will be shown in report summary information
MAX(MaxEventDuration) OVER() AS MaxPageLoadTime,
(SUM(EventDuration*EventCount) OVER())/(SUM(EventCount) OVER()) AS AveragePageLoadTime,
--Get ajax call flag
CASE WHEN EXISTS(
SELECT *
FROM #CLIENTEVENTS c
JOIN CSAJAX AS csaj (NOLOCK) ON csaj.cseventid = c.CSEVENTID
WHERE d.PageUri = c.PAGEURI
) THEN '*' ELSE ''
END AS Extension
FROM
PageEvents d
)
SELECT
[top].n AS Id,
-- Largest Pages
lp.PageUri AS lp_PageUri,
lp.EventCount AS lp_EventCount,
lp.ImageSize AS lp_ImageSize,
lp.CssStyleSize AS lp_CssStyleSize,
lp.HtcBehaviorSize AS lp_HtcBehaviorSize,
lp.ScriptSize AS lp_ScriptSize,
lp.HTMLSize AS lp_HTMLSize,
lp.AJAXCallSize AS lp_AJAXCallSize,
lp.TotalSize AS lp_TotalSize,
lp.EventDuration AS lp_EventDuration,
-- End Largest Pages
-- Slowest Pages
sp.PageUri AS sp_PageUri,
sp.EventCount AS sp_EventCount,
sp.NetworkTime AS sp_NetworkTime,
sp.ServerTime AS sp_ServerTime,
sp.DomTime AS sp_DomTime,
sp.PeripheralTime AS sp_PeripheralTime,
sp.OnLoadTime AS sp_OnLoadTime,
sp.TotalTime AS sp_TotalTime,
sp.Extension AS sp_Extension,
-- End Slowest Pages
-- Summary information
lp.TotalPageEventCount AS TotalPageEventCount,
lp.MaxPageSize,
lp.AveragePageSize,
sp.MaxPageLoadTime,
sp.AveragePageLoadTime
-- End Summary Information
FROM
APM.fn_nums(10) AS [top]
LEFT OUTER JOIN LargesPage AS lp ON [top].n = lp.Id
LEFT OUTER JOIN SlowestPage AS sp ON [top].n = sp.Id
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.SummaryPerformanceTopPages'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.SummaryPerformanceTopPages AS RETURN 1')
END
GO

/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: SummaryPerformanceTopPages */
/* USED IN: SummaryPerfTop5PageSubReport.rdl subreport */
/* INPUT PARAMETERS: */
/* @STARTDATE - Start date of the priod */
/* @ENDDATE - End date of the period */
/* @SOURCEID - SourceId */
/* @MACHINEIDS - List of machine Id, separated by comma. Exp: '4,5,6' */
/* @INCLUDESUBNET - Subnet masks list, which should be included */
/* @EXCLUDESUBNET - Subnet mask list, which should be excluded */
/* @THRESHOLD - Event threshold */
/************************************************************************************/
ALTER PROCEDURE APM.SummaryPerformanceTopPages
@STARTDATE DATETIME,
@ENDDATE DATETIME,
@SOURCEID INT,
@MACHINEIDS NVARCHAR(MAX),
@INCLUDESUBNET NVARCHAR(MAX),
@EXCLUDESUBNET NVARCHAR(MAX),
@THRESHOLD INT,
@PMSTATUS NVARCHAR(50)
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON

/****************************************************************************************/
/* ASSISTING TEMP TABLES */
/****************************************************************************************/

SELECT
@INCLUDESUBNET = REPLACE(@INCLUDESUBNET, N'*', N'%'),
@EXCLUDESUBNET = REPLACE(@EXCLUDESUBNET, N'*', N'%')

-- Filter table, which contains machine ids and source ids
-- valueId filter value - machine id
CREATE TABLE #MACHINEFILTERTABLE(
VALUEID INT
)

-- Fill table #SOURCEMACHINEFILTERTABLE
INSERT
INTO #MACHINEFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@MACHINEIDS, N'') AS p

-- Filter table for SubnetC values
CREATE TABLE #SUBNETCFILTERTABLE
(
IPID INT
)

-- Filter table, which contains PM Statuses of Events
CREATE TABLE #PMSTATUSFILTERTABLE(
VALUEID INT
)

-- Fill table #PMSTATUSFILTERTABLE
INSERT
INTO #PMSTATUSFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@PMSTATUS, N'') AS p

-- Insert into filter id of the SubnetC to increase performence for event table
INSERT INTO #SUBNETCFILTERTABLE
SELECT DISTINCT
ipid
FROM
APM.IP AS ip (NOLOCK)
JOIN APM.GetMultiParameters(CASE WHEN LEN(@INCLUDESUBNET) &gt; 0 THEN @INCLUDESUBNET ELSE N'%' END, N'') AS p1 ON (ip.SubnetC LIKE p1.Value)
LEFT OUTER JOIN APM.GetMultiParameters(CASE WHEN LEN(@EXCLUDESUBNET) &gt; 0 THEN @EXCLUDESUBNET ELSE N'Fake' END, N'') AS p2 ON (ip.SubnetC LIKE p2.Value)
WHERE
--Exclude subnets which have correspondance in @EXCLUDESUBNET parameter
p2.typeId IS NULL

CREATE TABLE #CLIENTEVENTS
(
CSEVENTID INT,
PAGEURI NVARCHAR(255) COLLATE DATABASE_DEFAULT
)

-- Filter Event Table by incoming parameters
INSERT INTO #CLIENTEVENTS
SELECT
e.CSEventId,
e.PageUri
FROM
APM.CSEVENT AS e (NOLOCK)
JOIN #MACHINEFILTERTABLE AS f ON (f.VALUEID = e.MachineId)
JOIN #SUBNETCFILTERTABLE AS f1 ON (f1.IPID = e.ipid)
JOIN #PMSTATUSFILTERTABLE AS f2 ON (f2.VALUEID = e.PMStatus)
WHERE
e.sourceId = @SOURCEID
AND UTCDATE &gt;= @STARTDATE
AND UTCDATE &lt; @ENDDATE
AND EventClass = 'CSMPMonitorLog'

;WITH CSPageEvents AS
(
SELECT
e.CSEVENTID,
e.PAGEURI,
-- Null values should be replaced by 0, to get convergence with Total time after averaging
COALESCE(pe.NetworkTime, 0) AS NetworkTime,
COALESCE(pe.ServerTime, 0) AS ServerTime,
COALESCE(pe.DOMTime, 0) AS DOMTime,
COALESCE(pe.PeripheralTime, 0) AS PeripheralTime,
COALESCE(pe.OnLoadTime, 0) AS OnLoadTime,
pe.TotalTime,
pe.TotalSize
FROM
#CLIENTEVENTS e
JOIN APM.CSPAGEEVENT AS pe (NOLOCK) ON pe.cseventid = e.CSEVENTID AND pe.TotalTime/1000.0 &gt;= @THRESHOLD

),
PageProcessingTime AS
(
SELECT
PageUri,
COUNT(CSEVENTID) AS EventCount,
AVG(NetworkTime)/1000 AS NetworkTime,
AVG(ServerTime)/1000 AS ServerTime,
AVG(DOMTime)/1000 AS DOMTime,
AVG(PeripheralTime)/1000 AS PeripheralTime,
AVG(OnLoadTime)/1000 AS OnLoadTime,
AVG(TotalTime)/1000 AS TotalTime,
AVG(TotalSize)/(1024.0) AS TotalSize
FROM
CSPageEvents
GROUP BY
PageUri
),
NumberedPages AS
(
SELECT
row_number() OVER(ORDER BY EventCount DESC) AS id,
PageUri,
EventCount,
NetworkTime,
ServerTime,
DOMTime,
PeripheralTime,
OnLoadTime,
TotalTime,
TotalSize,
SUM(EventCount) OVER() AS TotalEvents
FROM
PageProcessingTime
)
SELECT
TOP(5)
id,
PageUri,
EventCount,
NetworkTime,
ServerTime,
DOMTime,
PeripheralTime,
OnLoadTime,
TotalTime,
TotalSize,
TotalEvents,
--Get ajax call flag
CASE WHEN EXISTS(
SELECT *
FROM #CLIENTEVENTS c
JOIN CSPageEvent AS pe (NOLOCK) ON pe.cseventid = c.CSEVENTID
JOIN CSAJAX AS csaj (NOLOCK) ON csaj.cseventid = c.CSEVENTID
WHERE d.PageUri = c.PAGEURI
) THEN '*' ELSE ''
END AS Extension
FROM
NumberedPages d
ORDER BY id
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.ApplicationAnalysisExceptionEvents'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.ApplicationAnalysisExceptionEvents AS RETURN 1')
END
GO

/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: ApplicationAnalysisExceptionEvents */
/* USED IN: Application Analysis report for exception events */
/* INPUT PARAMETERS: */
/* @STARTDATE - Start date of the priod */
/* @ENDDATE - End date of the period */
/* @SOURCEID - SourceId */
/* @MACHINEIDS - List of machine Id, separated by comma. Exp: '4,5,6' */
/* @INCLUDESUBNET - List masks, which should be included */
/* @EXCLUDESUBNET - List masks, which should be excluded */
/************************************************************************************/
ALTER PROCEDURE APM.ApplicationAnalysisExceptionEvents
@STARTDATE DATETIME,
@ENDDATE DATETIME,
@SOURCEID NVARCHAR(MAX),
@MACHINEIDS NVARCHAR(MAX),
@INCLUDESUBNET NVARCHAR(MAX),
@EXCLUDESUBNET NVARCHAR(MAX),
@PMSTATUS NVARCHAR(50)
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON

/****************************************************************************************/
/* ASSISTING TEMP TABLES */
/****************************************************************************************/

SELECT
@INCLUDESUBNET = REPLACE(@INCLUDESUBNET, N'*', N'%'),
@EXCLUDESUBNET = REPLACE(@EXCLUDESUBNET, N'*', N'%')

-- Filter table, which contains machine ids
CREATE TABLE #MACHINEFILTERTABLE(
VALUEID INT
)

-- Fill table #MACHINEFILTERTABLE
INSERT
INTO #MACHINEFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@MACHINEIDS, N'') AS p

-- Filter table, which contains PM Statuses of Events
CREATE TABLE #PMSTATUSFILTERTABLE(
VALUEID INT
)

-- Fill table #PMSTATUSFILTERTABLE
INSERT
INTO #PMSTATUSFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@PMSTATUS, N'') AS p

-- Filter table for SubnetC values
CREATE TABLE #SUBNETCFILTERTABLE
(
IPID INT
)

-- Insert into filter id of the SubnetC to increase performence for event table
INSERT INTO #SUBNETCFILTERTABLE
SELECT DISTINCT
ipid
FROM
APM.IP AS ip (NOLOCK)
JOIN APM.GetMultiParameters(CASE WHEN LEN(@INCLUDESUBNET) &gt; 0 THEN @INCLUDESUBNET ELSE N'%' END, N'') AS p1 ON (ip.SubnetC LIKE p1.Value)
LEFT OUTER JOIN APM.GetMultiParameters(CASE WHEN LEN(@EXCLUDESUBNET) &gt; 0 THEN @EXCLUDESUBNET ELSE N'Fake' END, N'') AS p2 ON (ip.SubnetC LIKE p2.Value)
WHERE
--Exclude subnets which have correspondance in @EXCLUDESUBNET parameter
p2.typeId IS NULL

;WITH RequestPCTypeId AS
(
SELECT
PCTypeID
FROM
APM.PCTYPE
WHERE
TYPE = N'\Apps\Monitored Requests'
),
RequestCount AS
(
SELECT
SUM(SUMVALUE) AS RequestCount
FROM
APM.PerfHourly AS ph (NOLOCK)
-- Filter client events by machines
JOIN #MACHINEFILTERTABLE AS f1 ON (ph.MachineId = f1.VALUEID)
JOIN RequestPCTypeId AS pct ON pct.PCTypeID = ph.PCTypeID
WHERE
UTCDATE &gt;= @STARTDATE
AND UTCDATE &lt; @ENDDATE
AND ph.sourceid = @SOURCEID
),
EventDescription AS
(
SELECT
COUNT(CSEVENTID) AS EventCount,
COUNT(DISTINCT CSEVENTGROUPID) AS ProblemCount,
COUNT(CASE WHEN CHARINDEX(N'MSIE', E.BROWSER) &gt; 0 THEN E.CSEVENTID ELSE NULL END) AS IEEventCount,
COUNT(CASE WHEN CHARINDEX(N'Firefox', E.BROWSER) &gt; 0 THEN E.CSEVENTID ELSE NULL END) AS FirefoxEventCount,
DESCRIPTION
FROM
APM.CSEVENT AS e (NOLOCK)
-- Filter client events by machines
JOIN #MACHINEFILTERTABLE AS f1 ON (e.MachineId = f1.VALUEID)
-- Filter client events by subnets
JOIN #SUBNETCFILTERTABLE AS f2 ON (e.ipid = f2.IPID)
JOIN #PMSTATUSFILTERTABLE AS f3 ON (f3.VALUEID = e.PMStatus)
WHERE
e.ClassType = N'exception'
AND UTCDATE &gt; @STARTDATE
AND UTCDATE &lt; @ENDDATE
AND e.sourceid = @SOURCEID
GROUP BY
DESCRIPTION
),
OrderedDataSet AS
(
SELECT
ROW_NUMBER() OVER(ORDER BY E.EventCount DESC) AS id,
EventCount,
ProblemCount,
IEEventCount,
FirefoxEventCount,
Description,
SUM(E.EventCount) OVER() AS TotalEventCount,
SUM(E.ProblemCount) OVER() AS TotalProblemCount
FROM
EventDescription AS e
)
SELECT
TOP(10) E.*, req.RequestCount
FROM
OrderedDataSet AS e
CROSS JOIN RequestCount AS req
ORDER BY
E.ID
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.ApplicationAnalysisOverallStatistics'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.ApplicationAnalysisOverallStatistics AS RETURN 1')
END
GO

/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: ApplicationAnalysisOverallStatistics */
/* USED IN: Application Analysis report */
/* INPUT PARAMETERS: */
/* @STARTDATE - Start date of the priod */
/* @ENDDATE - End date of the period */
/* @SOURCEID - SourceId */
/* @MACHINEIDS - List of machine Id, separated by comma. Exp: '4,5,6' */
/* @INCLUDESUBNET - List masks, which should be included */
/* @EXCLUDESUBNET - List masks, which should be excluded */
/************************************************************************************/
ALTER PROCEDURE APM.ApplicationAnalysisOverallStatistics
@STARTDATE DATETIME,
@ENDDATE DATETIME,
@SOURCEID NVARCHAR(MAX),
@MACHINEIDS NVARCHAR(MAX),
@INCLUDESUBNET NVARCHAR(MAX),
@EXCLUDESUBNET NVARCHAR(MAX),
@PMSTATUS NVARCHAR(50)
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON

/****************************************************************************************/
/* ASSISTING TEMP TABLES */
/****************************************************************************************/
SELECT
@INCLUDESUBNET = REPLACE(@INCLUDESUBNET, N'*', N'%'),
@EXCLUDESUBNET = REPLACE(@EXCLUDESUBNET, N'*', N'%')

-- Filter table, which contains machine ids
CREATE TABLE #MACHINEFILTERTABLE(
VALUEID INT
)

-- Fill table #MACHINEFILTERTABLE
INSERT
INTO #MACHINEFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@MACHINEIDS, N'') AS p

-- Filter table, which contains PM Statuses of Events
CREATE TABLE #PMSTATUSFILTERTABLE(
VALUEID INT
)

-- Fill table #PMSTATUSFILTERTABLE
INSERT
INTO #PMSTATUSFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@PMSTATUS, N'') AS p

-- Filter table for SubnetC values
CREATE TABLE #SUBNETCFILTERTABLE
(
IPID INT
)

-- Insert into filter id of the SubnetC to increase performence for event table
INSERT INTO #SUBNETCFILTERTABLE
SELECT DISTINCT
ipid
FROM
APM.IP AS ip (NOLOCK)
JOIN APM.GetMultiParameters(CASE WHEN LEN(@INCLUDESUBNET) &gt; 0 THEN @INCLUDESUBNET ELSE N'%' END, N'') AS p1 ON (ip.SubnetC LIKE p1.Value)
LEFT OUTER JOIN APM.GetMultiParameters(CASE WHEN LEN(@EXCLUDESUBNET) &gt; 0 THEN @EXCLUDESUBNET ELSE N'Fake' END, N'') AS p2 ON (ip.SubnetC LIKE p2.Value)
WHERE
--Exclude subnets which have correspondance in @EXCLUDESUBNET parameter
p2.typeId IS NULL

CREATE TABLE #CLIENTEVENTS
(
CSEVENTID INT,
CSEVENTGROUPID INT,
CLASSTYPE NVARCHAR(50) COLLATE DATABASE_DEFAULT
)

INSERT INTO #CLIENTEVENTS
SELECT
e.cseventid,
e.csEventGroupId,
e.ClassType
FROM
APM.CSEVENT AS e (NOLOCK)
-- Filter client events by machines
JOIN #MACHINEFILTERTABLE AS f1 ON (e.MachineId = f1.VALUEID)
-- Filter client events by subnets
JOIN #SUBNETCFILTERTABLE AS f2 ON (e.ipid = f2.IPID)
JOIN #PMSTATUSFILTERTABLE AS f3 ON (f3.VALUEID = e.PMStatus)
WHERE
e.sourceid = @SOURCEID
AND UTCDATE &gt; @STARTDATE
AND UTCDATE &lt; @ENDDATE

;WITH RequestPCTypeId AS
(
SELECT
PCTypeID
FROM
APM.PCTYPE
WHERE
TYPE = N'\Apps\Monitored Requests'
),
RequestCount AS
(
SELECT
SUM(SUMVALUE) AS RequestCount
FROM
APM.PerfHourly AS ph
-- Filter client events by machines
JOIN #MACHINEFILTERTABLE AS f1 ON (ph.MachineId = f1.VALUEID)
JOIN RequestPCTypeId AS pct ON pct.PCTypeID = ph.PCTypeID
WHERE
ph.sourceid = @SOURCEID
AND UTCDATE &gt; @STARTDATE
AND UTCDATE &lt; @ENDDATE
),
AJAXEvents AS
(
SELECT
AVG(ajax.REQUESTSIZE + ajax.ResponseSize) AS AjaxCallSize,
AVG(ajax.TotalTime) AS AjaxCallDuration,
MAX(ajax.REQUESTSIZE + ajax.ResponseSize) AS MaxAjaxCallSize,
MAX(ajax.TotalTime) AS MaxAjaxCallDuration,
COUNT(ajax.CSEventId) AS AjaxCallCount
FROM
APM.CSAJAX AS ajax (NOLOCK)
JOIN #CLIENTEVENTS AS e ON ajax.CSEventId = e.CSEVENTID
WHERE
e.CLASSTYPE = N'performance'
),
ExceptionEvents AS
(
SELECT
COUNT(CSEVENTID) AS EventCount,
COUNT(CSEVENTGROUPID) AS ProblemCount
FROM
#CLIENTEVENTS AS e
WHERE
e.CLASSTYPE = N'exception'
),
PerformanceEvents AS
(
SELECT
COUNT(CSEVENTID) AS EventCount,
COUNT(CSEVENTGROUPID) AS ProblemCount
FROM
#CLIENTEVENTS AS e
WHERE
e.CLASSTYPE = N'performance'
)
SELECT
e.EventCount AS ExceptionEventsCount,
e.ProblemCount AS ExceptionProblemCount,
perf.EventCount AS PerformanceEventsCount,
perf.ProblemCount AS PerformanceProblemCount,
ajax.AjaxCallSize/1024.0 AS AjaxCallSize,
ajax.AjaxCallDuration/1000.0 AS AjaxCallDuration,
ajax.MaxAjaxCallSize/1024.0 AS MaxAjaxCallSize,
ajax.MaxAjaxCallDuration/1000.0 AS MaxAjaxCallDuration,
ajax.AjaxCallCount,
req.RequestCount
FROM
ExceptionEvents AS e
CROSS JOIN PerformanceEvents AS perf
CROSS JOIN RequestCount AS req
CROSS JOIN AJAXEvents AS ajax
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.SummaryPerformanceAnalysisReportTopJS'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.SummaryPerformanceAnalysisReportTopJS AS RETURN 1')
END
GO

/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: SummaryPerformanceAnalysisReportTopJS */
/* USED IN: Summary Performance Analysis Report */
/* INPUT PARAMETERS: */
/* @STARTDATE - Start date of the priod */
/* @ENDDATE - End date of the period */
/* @SOURCE - source Id */
/* @MACHINEIDS - List of machine Id, separated by comma. Exp: '4,5,6' */
/* @INCLUDESUBNET - Subnet masks list, which should be included */
/* @EXCLUDESUBNET - Subnet mask list, which should be excluded */
/* @THRESHOLD - Event threshold */
/************************************************************************************/

ALTER PROCEDURE APM.SummaryPerformanceAnalysisReportTopJS
@STARTDATE DATETIME,
@ENDDATE DATETIME,
@SOURCE INT,
@MACHINEIDS NVARCHAR(MAX),
@INCLUDESUBNET NVARCHAR(MAX),
@EXCLUDESUBNET NVARCHAR(MAX),
@THRESHOLD INT,
@PMSTATUS NVARCHAR(50)
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON

/****************************************************************************************/
/* ASSISTING TEMP TABLES */
/****************************************************************************************/

SELECT
@INCLUDESUBNET = REPLACE(@INCLUDESUBNET, N'*', N'%'),
@EXCLUDESUBNET = REPLACE(@EXCLUDESUBNET, N'*', N'%')

-- Filter table, which contains msource ids
CREATE TABLE #SOURCEFILTERTABLE(
VALUEID INT
)

-- Fill table #SOURCEMACHINEFILTERTABLE
INSERT
INTO #SOURCEFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@MACHINEIDS, N'') AS p

-- Filter table for SubnetC values
CREATE TABLE #SUBNETCFILTERTABLE
(
IPID INT
)

-- Insert into filter id of the SubnetC to increase performence for event table
INSERT INTO #SUBNETCFILTERTABLE
SELECT DISTINCT
ipid
FROM
APM.IP AS ip (NOLOCK)
JOIN APM.GetMultiParameters(CASE WHEN LEN(@INCLUDESUBNET) &gt; 0 THEN @INCLUDESUBNET ELSE N'%' END, N'') AS p1 ON (ip.SubnetC LIKE p1.Value)
LEFT OUTER JOIN APM.GetMultiParameters(CASE WHEN LEN(@EXCLUDESUBNET) &gt; 0 THEN @EXCLUDESUBNET ELSE N'Fake' END, N'') AS p2 ON (ip.SubnetC LIKE p2.Value)
WHERE
--Exclude subnets which have correspondance in @EXCLUDESUBNET parameter
p2.typeId IS NULL


-- Filter table, which contains PM Statuses of Events
CREATE TABLE #PMSTATUSFILTERTABLE(
VALUEID INT
)

-- Fill table #PMSTATUSFILTERTABLE
INSERT
INTO #PMSTATUSFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@PMSTATUS, N'') AS p

;WITH CSAjaxPageEvents AS
(
SELECT
e.CSEventID,
e.pageUri,
-- This name will be used only for Asynch Ajax Event, and for this events here will be only one row
MAX(ajax.uri) AS ActionName,
SUM(ajax.TotalTime) AS AJAXCallProcessingTime,
SUM(ajax.NetworkTime) AS NetworkTime,
SUM(ajax.ServerTime) AS ServerTime,
SUM(ajax.REQUESTSIZE) AS RequestSize,
SUM(ajax.ResponseSize) AS ResponseSize
FROM
APM.CSEVENT AS e (NOLOCK)
JOIN #SOURCEFILTERTABLE AS f1 ON (f1.VALUEID = e.MachineId)
JOIN #SUBNETCFILTERTABLE AS f2 ON e.ipid = f2.IPID
JOIN #PMSTATUSFILTERTABLE AS f3 ON (f3.VALUEID = e.PMStatus)
LEFT OUTER JOIN APM.CSAjax (NOLOCK) AS ajax ON ajax.cseventid = e.cseventid
WHERE
e.sourceId = @SOURCE
AND e.UTCDate &gt;= @STARTDATE
AND e.UTCDate &lt; @ENDDATE
AND e.EventClass &lt;&gt; N'CSMPMonitorLog'
GROUP BY
e.CSEventID,
e.pageUri
),
AJAXEventSummary AS
(
SELECT
e.CSEventID,
e.pageUri,
COALESCE(js.Action, e.ActionName) AS JSActionName,
COALESCE(js.TotalTime, e.AJAXCallProcessingTime) AS TotalTime,
COALESCE(js.TotalTime - COALESCE(e.AJAXCallProcessingTime, 0), asyncAjax.HandlerTime) AS ClientTime,
COALESCE(e.NetworkTime, 0) AS NetworkTime,
COALESCE(e.ServerTime, 0) AS ServerTime,
e.REQUESTSIZE,
e.ResponseSize
FROM
CSAjaxPageEvents AS e
LEFT OUTER JOIN APM.CSJScriptEvent AS js (NOLOCK) ON js.cseventid = e.cseventid
LEFT OUTER JOIN APM.CSAsyncAjax AS asyncAjax (NOLOCK) ON asyncAjax.cseventid = e.cseventid
WHERE
COALESCE(js.TotalTime, e.AJAXCallProcessingTime)/1000.0 &gt;= @THRESHOLD
),
AjaxPage AS
(
SELECT
JSActionName,
pageUri,
COUNT(CSEventID) AS EventCount,
AVG(ClientTime)/1000 AS ClientTime,
AVG(NetworkTime)/1000 AS NetworkTime,
AVG(ServerTime)/1000 AS ServerTime,
AVG(TotalTime)/1000 AS AJAXTotalTime,
AVG(RequestSize)/(1024.0) AS RequestSize,
AVG(ResponseSize)/(1024.0) AS ResponseSize
FROM
AJAXEventSummary
GROUP BY
JSActionName,pageUri
),
OrderedActions AS
(
SELECT
ROW_NUMBER() OVER(ORDER BY EventCount DESC) AS id,
EventCount,
JSActionName,
pageUri,
ClientTime,
NetworkTime,
ServerTime,
AJAXTotalTime AS TotalTime,
RequestSize + ResponseSize AS AJAXCallSize,
SUM(EventCount) OVER() AS TotalEvents
FROM
AjaxPage
)
SELECT TOP(5)
*
FROM
OrderedActions
ORDER BY
id
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.ApplicationActivityBreakdownByMonthDate'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.ApplicationActivityBreakdownByMonthDate AS RETURN 1')
END
GO

/****************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: ApplicationActivityBreakdownByMonthDate */
/* USED IN: Application Status Report, Application Activity */
/* DESCRIPTION: This SP is used in report above in case, when grouping by month date */
/* specified */
/* INPUT PARAMETERS: */
/* @SOURCEIDS - List of the source id, separated by comma. Exp: '1,2,3' */
/* @COMPUTERIDS - List of the computer id, separated by comma. Exp: '1,2,3' */
/* @ENDDATE - End date of the period in Client time zone */
/* @PERIOD - Period type(Day, Week or Month). */
/* - Use for the Start Date calculate of the period */
/* @AVERAGEINTERVAL- This value specifies interval, for which average values will */
/* be calculated. Possible values: 1(1 month), 2(2 month), */
/* 3(3 month), 6(6 month), 17 (7 day) */
/* @GROUPBY - Specifies result gouping type. Possible values: */
/* Hour - Group by hours. Rersult set will contain 24 rows */
/* corresponding to 24 hours. Date field - 0-23, Hour field - 0 */
/* WeekDay - Group by week days. For this grouping type extra grouping */
/* is applied - by hours. So result data set contains 7*24 rows. */
/* Date field values - 1-7, Hour fields - 0-23 */
/* Month - Group by Month. For this grouping type extra grouping */
/* is applied - by months. So result data set contains 12*24 rows. */
/* and Hour field - 0-23 */
/* @TRESHOLD - Event duration treshold */
/* @PROBLEM - Event problem type (all, critical) */
/* @TIMEZONE - correlate parameter (timezone by min) */
/* - for the End Date calculate */
/****************************************************************************************/
ALTER PROCEDURE APM.ApplicationActivityBreakdownByMonthDate
@SOURCEIDS NVARCHAR(MAX),
@COMPUTERIDS NVARCHAR(MAX),
@ENDDATE DATETIME,
@TIMEZONE INT,
@PERIOD INT,
@AVERAGEINTERVAL INT,
@GROUPBY NVARCHAR(10),
@THRESHOLD INT,
@PROBLEM NVARCHAR(10),
@PMSTATUS NVARCHAR(50)
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON;

/************************************************************************************/
/* Prepare auxiliary variables for the further calculation */
/************************************************************************************/

--Used for counting average value for last three months
DECLARE @PERIODDAYSCOUNT int
SET @PERIODDAYSCOUNT = 31

SET @ENDDATE = DATEADD(minute, -@TIMEZONE, @ENDDATE)

DECLARE @STARTDATE DateTime
SET @STARTDATE = DATEADD(d, -@PERIODDAYSCOUNT, @ENDDATE)

DECLARE @LASTPERIODSTARTDATE DateTime
SET @LASTPERIODSTARTDATE = DATEADD(d, -@PERIODDAYSCOUNT, @STARTDATE)

DECLARE @AVERAGEPERIODSTARTDATE DateTime
SET @AVERAGEPERIODSTARTDATE = (CASE
WHEN @AVERAGEINTERVAL &lt; 10 THEN DATEADD(month, -@AVERAGEINTERVAL, @STARTDATE)
ELSE DATEADD(day, -(@AVERAGEINTERVAL-10), @STARTDATE)
END)

DECLARE @PROCESSORCOUNTERID INT
SELECT @PROCESSORCOUNTERID = PCtypeId FROM APM.PCType (NOLOCK) WHERE type = N'\Process\% Processor Time'

DECLARE @MEMORYCOUNTERID INT
SELECT @MEMORYCOUNTERID = PCtypeId FROM APM.PCType (NOLOCK) WHERE type = N'\Process\Private Bytes'

DECLARE @IOCOUNTERID INT
SELECT @IOCOUNTERID = PCtypeId FROM APM.PCType (NOLOCK) WHERE type = N'\Process\IO Data Bytes/sec'

DECLARE @MONITOREDREQUESTCOUNTERID INT
SELECT @MONITOREDREQUESTCOUNTERID = PCtypeId FROM APM.PCType (NOLOCK) WHERE type = N'\Apps\Monitored Requests'

DECLARE @REQUESTTIMECOUNTERID INT
SELECT @REQUESTTIMECOUNTERID = PCtypeId FROM APM.PCType (NOLOCK) WHERE type = N'\Apps\Avg. Request Time'

/************************************************************************************/
/* ASSISTING TEMP TABLES */
/************************************************************************************/
-- Filter table, which contains machine ids and source ids
-- typeid defines filter type - 1 for source and 2 for machine
-- valueId filter value - source id and machine id
CREATE TABLE #SOURCEMACHINEFILTERTABLE(
TYPEID INT,
VALUEID INT
)

-- Fill table #SOURCEMACHINEFILTERTABLE
INSERT
INTO #SOURCEMACHINEFILTERTABLE
SELECT
p.typeId AS TYPEID,
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@SOURCEIDS, @COMPUTERIDS) AS p

-- Filter table, which contains PM Statuses of Events
CREATE TABLE #PMSTATUSFILTERTABLE(
VALUEID INT
)

-- Fill table #PMSTATUSFILTERTABLE
INSERT
INTO #PMSTATUSFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@PMSTATUS, N'') AS p

-- To form application pool with all sources run in it, it is need to get all sources and its process
CREATE TABLE #PROCESSFORSOURCE
(
SOURCEID INT,
PCPROCESSID INT,
MACHINEID INT,
EXTRAINFO NVARCHAR(255) COLLATE DATABASE_DEFAULT,
PROCESS NVARCHAR(255) COLLATE DATABASE_DEFAULT
)

INSERT INTO #PROCESSFORSOURCE
SELECT
ph.SourceId,
ph.PCProcessId,
ph.MachineId,
COALESCE(p.Extrainfo, N'') AS EXTRAINFO,
--Select process name till # symbol (w3wp#1 -&gt; w3wp, w3wp -&gt; w3wp)
APM.RemoveProcessIdFromName(p.Process) AS Process
FROM
(
SELECT DISTINCT
ph.SourceId,
ph.pcprocessId,
ph.MachineId
FROM
APM.PerfHourly AS ph (NOLOCK)
WHERE
ph.pcprocessId IS NOT NULL
AND ph.UTCDate &gt;= @STARTDATE
AND ph.UTCDate &lt; @ENDDATE
) AS ph
JOIN APM.PCProcess AS p (NOLOCK) ON p.pcprocessId = ph.pcprocessId
JOIN #SOURCEMACHINEFILTERTABLE AS f ON (f.TYPEID = 2 AND ph.MachineId = f.VALUEID)


-- Report frame. It contains all sources, for which values sould be selected,
-- and dates for the specified period (StartDate : EndDate)
;WITH SourcesDates AS
(
SELECT
VALUEID AS sourceid,
s.source AS source,
-- Select 31 day from end date in ClientTime zone, without hours
CONVERT(NVARCHAR, DATEADD(d, -d.n, DATEADD(minute, @TIMEZONE, @ENDDATE)), 112) AS ClientDate
FROM
#SOURCEMACHINEFILTERTABLE AS source
JOIN APM.source (NOLOCK) AS s ON s.sourceid = source.VALUEID
CROSS JOIN APM.fn_nums(31) AS d
WHERE
source.TYPEID = 1
),
AppPoolInfo AS
(
SELECT
c.SOURCEID,
c.EXTRAINFO,
c.PROCESS,
-- all source names which have the same process name as passed in @SOURCEIDS
(SELECT A.source AS [data()]
FROM
(
SELECT DISTINCT
N'''' + s.source + N'''' + N',' AS source
FROM
#PROCESSFORSOURCE AS c1
JOIN APM.Source AS s ON c1.SOURCEID = s.SourceId
WHERE
c1.EXTRAINFO = c.EXTRAINFO
AND c1.PROCESS = c.PROCESS
AND c1.MACHINEID = c.MACHINEID
) AS A
FOR XML PATH ('')
) AS AppPoolSources
FROM
#PROCESSFORSOURCE AS c
JOIN #SOURCEMACHINEFILTERTABLE AS f ON (f.TYPEID = 1 AND f.VALUEID = c.SOURCEID)
GROUP BY
c.SOURCEID,
c.MACHINEID,
c.EXTRAINFO,
c.PROCESS
),
--Add Pool name in-front of source list, if it is executable application, then app pool countains source name
PrepareAppPoolInfo AS (
SELECT DISTINCT
CASE
WHEN COALESCE(info.ExtraInfo,'') = '' THEN CASE info.AppPoolSources WHEN '' THEN '' ELSE LEFT(info.AppPoolSources, LEN(info.AppPoolSources)-1) END
ELSE info.ExtraInfo + CASE info.AppPoolSources WHEN '' THEN '' ELSE ' (' + LEFT(info.AppPoolSources, LEN(info.AppPoolSources) - 1) + ')' END
END AppPool,
info.SourceId,
info.ExtraInfo
FROM
AppPoolInfo AS info
),
-- Forms application pool list for each source
-- Format: AppPool1 ('Source1', 'Source2', Source3), AppPool2 ('Source1', 'Source4')
SourceAppPools AS (
SELECT
s.SourceId,
s.Source,
COALESCE((SELECT a.AppPool AS [data()]
FROM
(
SELECT DISTINCT
info.AppPool + N',' AS AppPool
FROM
PrepareAppPoolInfo as info
WHERE
info.Sourceid = s.Sourceid
) AS A
FOR XML PATH ('')
),s.Source + '-') AS AppPoolInfo
FROM
APM.Source AS s
JOIN #SOURCEMACHINEFILTERTABLE AS f ON (f.TYPEID = 1 AND f.VALUEID = s.SourceId)
),
--Prepares and filters events for further manipulations
ActivityBreakdown_EventsFiltered AS
(
SELECT
e.sourceid,
e.eventid,
e.utceventdate AS eventdate,
-- Event Date in Client Timezone without hours
CONVERT(NVARCHAR, DATEADD(minute, @TIMEZONE, e.utceventdate), 112) AS ClientDate,
--hour is taken as DateDifference in day between 05/04/2009 9:00AM and 05/03/2009 9:00PM is one day,
--despite in case of @PERIOD = 'Day' it can be interpretated as one day (if 05/04/2009 9:00AM is end date), so difference should be taken as 0
ABS(DATEDIFF(hour, e.utceventdate, @ENDDATE)) / (@PERIODDAYSCOUNT*24) AS PeriodId,
e.eventgroupid,
db.ADDRESS AS SeViewerAddress
FROM
APM.Event AS e
JOIN APM.SeViewerDB AS db ON e.seviewerdbid = db.seviewerdbid
JOIN #SOURCEMACHINEFILTERTABLE AS f1 ON (f1.VALUEID = e.sourceid and f1.TYPEID = 1)
JOIN #SOURCEMACHINEFILTERTABLE AS f2 ON (f2.VALUEID = e.machineid and f2.TYPEID = 2)
JOIN #PMSTATUSFILTERTABLE AS f3 ON (f3.VALUEID = e.PMStatus)
WHERE
((e.EventClassType = N'Performance' AND e.eventduration / 1000000.0 &gt;= @THRESHOLD)
OR e.EventClassType = N'exception')
AND (e.category LIKE @PROBLEM OR e.category IS NULL)
AND e.utceventdate &gt;= @AVERAGEPERIODSTARTDATE
AND e.utceventdate &lt; @ENDDATE
AND (e.HeavyLight &lt;&gt; 0 OR e.HeavyLight IS NULL)

),
/************************************************************************************/
/* Base pcounter queries */
/************************************************************************************/
-- Calculate resource utilization by Source in one hour.
-- Aggregation between instances should be done here (for cases when one source run in several process in one hour)
SourceHourlyResourceUtilization AS
(
SELECT
ph.MachineId,
ph.SourceId,
-- PerfHourly date in client time zone without hours
CONVERT(NVARCHAR, DATEADD(minute, @TIMEZONE ,ph.UTCDate), 112) AS ClientDate,
ph.PCTypeId AS Type,

---------- Pivot instance count by period type -----------
(CASE
WHEN ph.UtcDate &gt;= @LASTPERIODSTARTDATE AND ph.UtcDate &lt; @STARTDATE
THEN SUM(ph.SampleCount)*1.0/MAX(ph.PackageCounter)
END) AS LastInstanceCount,
(CASE
WHEN ph.UtcDate &gt;= @STARTDATE AND ph.UtcDate &lt; @ENDDATE
THEN SUM(ph.SampleCount)*1.0/MAX(ph.PackageCounter)
END) AS CurInstanceCount,
(CASE
WHEN ph.utcdate &gt;= @AVERAGEPERIODSTARTDATE AND ph.utcdate &lt; @STARTDATE
THEN SUM(ph.SampleCount)*1.0/MAX(ph.PackageCounter)
END) AS AvgInstanceCount,

---------- Pivot resource value by period type -----------
(CASE
WHEN ph.UtcDate &gt;= @LASTPERIODSTARTDATE AND ph.UtcDate &lt; @STARTDATE THEN SUM(SumValue)/SUM(SampleCount)
END) AS LastValue,
(CASE
WHEN ph.UtcDate &gt;= @STARTDATE AND ph.UtcDate &lt; @ENDDATE THEN SUM(SumValue)/SUM(SampleCount)
END) AS CurValue,
(CASE
WHEN ph.utcdate &gt;= @AVERAGEPERIODSTARTDATE AND ph.utcdate &lt; @STARTDATE THEN SUM(SumValue)/SUM(SampleCount)
END) AS AvgValue,
ABS(DATEDIFF(hour, ph.UTCDate, @ENDDATE)) / (@PERIODDAYSCOUNT*24) AS PeriodId
FROM
APM.PerfHourly AS ph (NOLOCK)
--Join with #SOURCEMACHINEFILTERTABLE with typeid = 1 provides filtering perfHourly by sourceid
JOIN #SOURCEMACHINEFILTERTABLE AS f1 ON (f1.TYPEID = 1 AND f1.VALUEID = ph.SourceId)
--Join with #SOURCEMACHINEFILTERTABLE with typeid = 2 provides filtering perfHourly by machineid
JOIN #SOURCEMACHINEFILTERTABLE AS f2 ON (f2.TYPEID = 2 AND f2.VALUEID = ph.MachineId)
WHERE
ph.UTCDate &gt;= @AVERAGEPERIODSTARTDATE
AND ph.UTCDate &lt; @ENDDATE
AND ph.PCTypeId IN (@PROCESSORCOUNTERID, @IOCOUNTERID, @MEMORYCOUNTERID)
GROUP BY
ph.MachineId,
ph.SourceId,
ph.UTCDate,
ph.PCTypeId
),
-- Bring ClientDate to current period, as in result data set, data only for current period are shown
-- (all other should be shown relative to current period)
SourceHourlyResourceUtilizationByCurrentPeriod AS
(
SELECT
ph.MachineId,
ph.SourceId,
-- PeriodId is 0 for the current period, 1 for last and 1..n for average
-- this manipulation should bring Client date to current period
DATEADD(day, ph.PeriodId*31, ClientDate) AS ClientDate,
ph.Type,
ph.LastInstanceCount,
ph.CurInstanceCount,
ph.AvgInstanceCount,
ph.LastValue,
ph.CurValue,
ph.AvgValue,
ph.PeriodId
FROM
SourceHourlyResourceUtilization AS ph
),
--Calculate average source resource utilization for each resource type
--and for specified grouping period and date
ApplicationResourceUtilizationByMachines AS
(
SELECT
ph.MachineId,
ph.SourceId,
ph.PeriodId,
ph.ClientDate,
-- Instance count should be same for different resource types in one hour for one process
-- and averaging them won't make any difference but allow to avoid one aggregation step
AVG(ph.CurInstanceCount) AS CurInstanceCount,
AVG(ph.LastInstanceCount) AS LastInstanceCount,
AVG(ph.AvgInstanceCount) AS AvgInstanceCount,

---------- Pivot resource by counter type -----------

----------- 'Process% Processor Time' counter -------------------
AVG(CASE WHEN ph.type = @PROCESSORCOUNTERID THEN ph.CurValue END) AS CurCPUSum,
AVG(CASE WHEN ph.type = @PROCESSORCOUNTERID THEN ph.LastValue END) AS LastCPUSum,
AVG(CASE WHEN ph.type = @PROCESSORCOUNTERID THEN ph.AvgValue END) AS AvgCPUSum,

----------- 'ProcessPrivate Bytes' counter -------------------
AVG(CASE WHEN ph.type = @MEMORYCOUNTERID THEN ph.CurValue END) AS CurMemSum,
AVG(CASE WHEN ph.type = @MEMORYCOUNTERID THEN ph.LastValue END) AS LastMemSum,
AVG(CASE WHEN ph.type = @MEMORYCOUNTERID THEN ph.AvgValue END) AS AvgMemSum,

----------- 'ProcessIO Data Bytes/sec' counter -------------------
AVG(CASE WHEN ph.type = @IOCOUNTERID THEN ph.CurValue END) AS CurIOSum,
AVG(CASE WHEN ph.type = @IOCOUNTERID THEN ph.LastValue END) AS LastIOSum,
AVG(CASE WHEN ph.type = @IOCOUNTERID THEN ph.AvgValue END) AS AvgIOSum
FROM
SourceHourlyResourceUtilizationByCurrentPeriod AS ph
GROUP BY
ph.MachineId,
ph.SourceId,
ph.PeriodId,
ph.ClientDate
),
-- Count Monitored Requests and Avg. Request Timefor Application on each machine
-- as source can run on different machines with same process name and app pool, but different sources set,
-- it is important to group by machine to, to avoid calculation of requests from the other app pool
-- Summarize request count in each period (PeriodId differs only for AvgValue)
ApplicationNetAppCountersByMachinePrepare AS
(
SELECT
ph.MachineId,
ph.SourceId,
CONVERT(NVARCHAR, DATEADD(minute, @TIMEZONE, ph.UTCDate), 112) AS ClientDate,
----------------- Pivot Monitor Request Counter by period ------------------
CASE WHEN ph.UtcDate &gt;= @LASTPERIODSTARTDATE AND ph.UtcDate &lt; @STARTDATE
THEN SUM(CASE WHEN ph.PCTypeId = @MONITOREDREQUESTCOUNTERID THEN ph.SumValue END)
END AS LastMonRequest,
CASE WHEN ph.UtcDate &gt;= @STARTDATE AND ph.UtcDate &lt; @ENDDATE
THEN SUM(CASE WHEN ph.PCTypeId = @MONITOREDREQUESTCOUNTERID THEN ph.SumValue END)
END AS CurMonRequest,
CASE WHEN ph.utcdate &gt;= @AVERAGEPERIODSTARTDATE AND ph.utcdate &lt; @STARTDATE
THEN SUM(CASE WHEN ph.PCTypeId = @MONITOREDREQUESTCOUNTERID THEN ph.SumValue END)
END AS AvgMonRequest,

----------------- Pivot Avg. Request Time Counter by period ------------------
CASE WHEN ph.UtcDate &gt;= @LASTPERIODSTARTDATE AND ph.UtcDate &lt; @STARTDATE
THEN AVG(CASE WHEN ph.PCTypeId = @REQUESTTIMECOUNTERID THEN ph.SumValue / ph.SampleCount END)
END AS LastAvgReqTime,
CASE WHEN ph.UtcDate &gt;= @STARTDATE AND ph.UtcDate &lt; @ENDDATE
THEN AVG(CASE WHEN ph.PCTypeId = @REQUESTTIMECOUNTERID THEN ph.SumValue / ph.SampleCount END)
END AS CurAvgReqTime,
CASE WHEN ph.utcdate &gt;= @AVERAGEPERIODSTARTDATE AND ph.utcdate &lt; @STARTDATE
THEN AVG(CASE WHEN ph.PCTypeId = @REQUESTTIMECOUNTERID THEN ph.SumValue / ph.SampleCount END)
END AS AvgReqTime,

ABS(DATEDIFF(hour, ph.UTCDate, @ENDDATE)) / (@PERIODDAYSCOUNT*24) AS PeriodId
FROM
apm.PerfHourly AS ph (NOLOCK)
--Join with #SOURCEMACHINEFILTERTABLE provides filtering perfHourly by sourceid
JOIN #SOURCEMACHINEFILTERTABLE AS f1 ON (f1.TYPEID = 1 AND ph.SourceId = f1.VALUEID)
--Join with #SOURCEMACHINEFILTERTABLE provides filtering perfHourly by machineid
JOIN #SOURCEMACHINEFILTERTABLE AS f2 ON (f2.TYPEID = 2 AND f2.VALUEID = ph.MachineId)
WHERE
ph.UTCDate &gt;= @AVERAGEPERIODSTARTDATE
AND ph.UTCDate &lt; @ENDDATE
AND ph.PCTypeID IN (@REQUESTTIMECOUNTERID, @MONITOREDREQUESTCOUNTERID)
GROUP BY
ph.MachineId,
ph.SourceId,
ph.UTCDate
),
-- Bring ClientDate to current period, as in result data set, data only for current period are shown
-- (all other should be shown relative to current period)
ApplicationNetAppCountersByCurrentPeriod AS
(
SELECT
ph.MachineId,
ph.SourceId,
-- PeriodId is 0 for the current period, 1 for last and 1..n for average
-- this manipulation should bring Client date to current period
DATEADD(day, ph.PeriodId*31, ClientDate) AS ClientDate,
ph.LastMonRequest,
ph.CurMonRequest,
ph.AvgMonRequest,
ph.LastAvgReqTime,
ph.CurAvgReqTime,
ph.AvgReqTime,
ph.PeriodId
FROM
ApplicationNetAppCountersByMachinePrepare AS ph
),
--Calculate average request time and sum request count for specified grouping period and date
ApplicationNetAppCountersByMachine AS
(
SELECT
ph.MachineId,
ph.SourceId,
ph.PeriodId,
ph.ClientDate,
SUM(ph.LastMonRequest) AS LastMonRequest,
SUM(ph.CurMonRequest) AS CurMonRequest,
SUM(ph.AvgMonRequest) AS AvgMonRequest,
AVG(ph.LastAvgReqTime) AS LastAvgReqTime,
AVG(ph.CurAvgReqTime) AS CurAvgReqTime,
AVG(ph.AvgReqTime) AS AvgReqTime
FROM
ApplicationNetAppCountersByCurrentPeriod ph
GROUP BY
ph.MachineId,
ph.SourceId,
ph.PeriodId,
ph.ClientDate
),
-- Union .NET counters and process counters for period Id. Period Id differs only for average(last three months) values, so grouping only for them
PCountersGroupedByMachineId AS (
SELECT
pc.machineId,
pc.SourceId,
pc.ClientDate,

MAX(netApp.CurMonRequest) AS CurReqCount,
MAX(netApp.LastMonRequest) AS LastReqCount,
AVG(netApp.AvgMonRequest) AS AvgReqCount,

MAX(netApp.CurAvgReqTime) AS CurAvgReqTime,
MAX(netApp.LastAvgReqTime) AS LastAvgReqTime,
AVG(netApp.AvgReqTime) AS AvgReqTime,

MAX(pc.CurCPUSum) AS CurCPUSum,
MAX(pc.LastCPUSum) AS LastCPUSum,
AVG(pc.AvgCPUSum) AS AvgCPUSum,
MAX(pc.CurMemSum) AS CurMemSum,
MAX(pc.LastMemSum) AS LastMemSum,
AVG(pc.AvgMemSum) AS AvgMemSum,
MAX(pc.CurIOSum) AS CurIOSum,
MAX(pc.LastIOSum) AS LastIOSum,
AVG(pc.AvgIOSum) AS AvgIOSum
FROM ApplicationResourceUtilizationByMachines pc
LEFT JOIN ApplicationNetAppCountersByMachine AS netApp ON netApp.MachineId = pc.MachineId
AND netApp.SourceId = pc.SourceId AND netApp.PeriodId = netApp.PeriodId
AND netApp.ClientDate = pc.ClientDate
GROUP BY
pc.machineId,
pc.SourceId,
pc.ClientDate
),
-- Calculate average source resource utilization between machines
ActivePreparePCounters AS (
SELECT
pc.SourceId,
-- Convert date to appropriate format to provide correct comparison
pc.ClientDate,
SUM(CurReqCount) AS CurReqCount,
SUM(LastReqCount) AS LastReqCount,
SUM(AvgReqCount) AS AvgReqCount,
AVG(CurAvgReqTime) AS CurAvgReqTime,
AVG(LastAvgReqTime) AS LastAvgReqTime,
AVG(AvgReqTime) AS AvgReqTime,
AVG(CurCPUSum / COALESCE(m.CPUCount, 1)) AS CurCPUSum,
AVG(LastCPUSum / COALESCE(m.CPUCount, 1) ) AS LastCPUSum,
AVG(AvgCPUSum / COALESCE(m.CPUCount, 1)) AS AvgCPUSum,


AVG(CurMemSum) AS CurMemSum,
AVG(LastMemSum) AS LastMemSum,
AVG(AvgMemSum) AS AvgMemSum,
AVG(CurIOSum) AS CurIOSum,
AVG(LastIOSum) AS LastIOSum,
AVG(AvgIOSum) AS AvgIOSum
FROM
PCountersGroupedByMachineId AS pc
JOIN apm.Machine AS m ON m.MachineId = pc.MachineId
GROUP BY
pc.SourceId,
pc.ClientDate
),
-- Count events for the current, last and average period.
-- PeriodId is 0 for Current period, 1 for last period, and 1..n for average period
PrepareEventsAvg AS
(
SELECT
e.sourceid AS sourceid,
-- PeriodId is 0 for the current period, 1 for last and 1..n for average
-- this manipulation should bring Client date to current period
DATEADD(day, e.PeriodId*31, e.ClientDate) AS ClientDate,
e.PeriodId,
MAX(E.SeViewerAddress) AS SeViewerAddress,
COUNT(CASE WHEN e.eventdate &gt;= @STARTDATE AND e.eventdate &lt; @ENDDATE THEN eventid END) AS CurrentEventsCount,
COUNT(CASE WHEN e.eventdate &gt;= @LASTPERIODSTARTDATE AND e.eventdate &lt; @STARTDATE THEN eventid END) AS LasEventsCount,
COUNT(CASE WHEN E.eventdate &gt;= @AVERAGEPERIODSTARTDATE AND E.eventdate &lt; @STARTDATE THEN eventid END) AS AvgEventsCount
FROM
ActivityBreakdown_EventsFiltered AS e
GROUP BY
e.sourceid,
e.PeriodId,
e.ClientDate
),
Events AS
(
SELECT
e.sourceid AS sourceid,
-- Convert date to appropriate format to provide correct comparison
e.ClientDate,
MAX(E.SeViewerAddress) AS SeViewerAddress,
--PeriodId differs only for average, so for current and last period it doesn't matter which agg function is taken
MAX(CurrentEventsCount) AS CurrentEventsCount,
MAX(LasEventsCount) AS LasEventsCount,
--Average counting is not included current period
AVG(AvgEventsCount) AS AvgEventsCount
FROM
PrepareEventsAvg AS e
GROUP BY
sourceid,
e.ClientDate
),
-- Check that CPU count is defined for all computers, where application run.
-- Computers set, where application run, does not depend on specified period by design, as otherwise there is performance problems
MachineCPUUndefinedFlag AS
(
SELECT
sf.SOURCEID,
MIN(COALESCE(m.CPUCount, -1)) AS CPUUndefinedFlag
FROM
#PROCESSFORSOURCE AS sf
JOIN apm.Machine AS m (NOLOCK) ON sf.MACHINEID = m.MachineId
GROUP BY
sf.SOURCEID
)
SELECT
-- Convert to ISO8601 format to work properly with VB Script. This cannot be done earlier as join is done on this fields
CONVERT(DATETIME, SourcesDates.ClientDate, 126) AS ClientDate,
-- These fake fields are need to provide compatibility with SP ApplicationStatusDrillthrough
1 AS Date,
0 AS Hours,
1 AS OutputDate,
1 AS Period,
SourcesDates.Sourceid,
SourcesDates.Source AS Source,
COALESCE(pc.CurReqCount, 0) AS CurMonitoredRequestSum,
COALESCE(pc.LastReqCount, 0) AS LastMonitoredRequestSum,
COALESCE(pc.AvgReqCount, 0) AS AvgMonitoredRequestSum,
COALESCE(pc.CurAvgReqTime, 0) AS CurAvgReqTime,
COALESCE(pc.LastAvgReqTime, 0) AS LastAvgReqTime,
COALESCE(pc.AvgReqTime, 0) AS AvgReqTime,
COALESCE(pc.CurCPUSum, 0) AS CurCPUValue,
COALESCE(pc.lastCPUSum, 0) AS LastCPUValue,
COALESCE(pc.AvgCPUSum, 0) AS AvgValue,
COALESCE(pc.CurMemSum, 0) AS CurMemValue,
COALESCE(pc.LastMemSum, 0) AS LastMemValue,
COALESCE(pc.AvgMemSum, 0) AS AvgMemValue,
COALESCE(pc.CurIOSum, 0) AS CurIOValue,
COALESCE(pc.LastIOSum, 0) AS LastIOValue,
COALESCE(pc.AvgIOSum, 0) AS AvgIOValue,
COALESCE(e.CurrentEventsCount, 0) AS NewEventsCount,
COALESCE(e.LasEventsCount, 0) AS OldEventsCount,
COALESCE(e.AvgEventsCount, 0) AS AvgEventsCount,
-- cpuFlag.CPUUndefinedFlag is null for current source if there is no one PCounter row
-- in PerfHourly table for specified period. If so, there is no need to show message about it
COALESCE(cpuFlag.CPUUndefinedFlag, 1) AS CPUUndefinedFlag,
CASE LEFT(AppPool.AppPoolInfo,1)
WHEN N'''' THEN N''
WHEN N'' THEN ''
ELSE REPLACE(LEFT(AppPool.AppPoolInfo, LEN(AppPool.AppPoolInfo)-1), N'''', N'')
END AS pool,
E.SeViewerAddress
FROM
SourcesDates
LEFT OUTER JOIN MachineCPUUndefinedFlag AS cpuFlag ON SourcesDates.Sourceid = cpuFlag.Sourceid
LEFT OUTER JOIN ActivePreparePCounters AS pc ON (pc.ClientDate = SourcesDates.ClientDate AND pc.SourceId = SourcesDates.Sourceid)
LEFT OUTER JOIN Events AS e ON (e.ClientDate = SourcesDates.ClientDate AND e.Sourceid = SourcesDates.Sourceid)
JOIN SourceAppPools AS AppPool ON (AppPool.Sourceid = SourcesDates.Sourceid)
ORDER BY
Source,
ClientDate
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.ApplicationActivityBreakdown'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.ApplicationActivityBreakdown AS RETURN 1')
END
GO

/****************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: ApplicationActivityBreakdown */
/* USED IN: Application Status Report, Application Activity */
/* DESCRIPTION: Temporary SP which provides unique call for different group by */
/* parameters, which realy need different SP */
/* INPUT PARAMETERS: */
/* @SOURCEIDS - List of the source id, separated by comma. Exp: '1,2,3' */
/* @COMPUTERIDS - List of the computer id, separated by comma. Exp: '1,2,3' */
/* @ENDDATE - End date of the period */
/* @PERIOD - Period type(Day, Week or Month). */
/* - Use for the Start Date calculate of the period */
/* @AVERAGEINTERVAL- This value specifies interval, for which average values will */
/* be calculated. Possible values: 1(1 month), 2(2 month), */
/* 3(3 month), 6(6 month), 17 (7 day) */
/* @GROUPBY - Specifies result gouping type. Possible values: */
/* Hour - Group by hours. Rersult set will contain 24 rows */
/* corresponding to 24 hours. Date field - 0-23, Hour field - 0 */
/* WeekDay - Group by week days. For this grouping type extra grouping */
/* is applied - by hours. So result data set contains 7*24 rows. */
/* Date field values - 1-7, Hour fields - 0-23 */
/* Month - Group by Month. For this grouping type extra grouping */
/* is applied - by months. So result data set contains 12*24 rows. */
/* and Hour field - 0-23 */
/* @TRESHOLD - Event duration treshold */
/* @PROBLEM - Event problem type (all, critical) */
/* @TIMEZONE - correlate parameter (timezone by min) */
/* - for the End Date calculate */
/****************************************************************************************/
alter PROCEDURE APM.ApplicationActivityBreakdown
@SOURCEIDS NVARCHAR(MAX),
@COMPUTERIDS NVARCHAR(MAX),
@ENDDATE DATETIME,
@TIMEZONE INT,
@PERIOD INT,
@AVERAGEINTERVAL INT,
@GROUPBY NVARCHAR(10),
@THRESHOLD INT,
@PROBLEM NVARCHAR(10),
@PMSTATUS NVARCHAR(50)
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON;

IF @GROUPBY = 'MonthDay'
exec APM.ApplicationActivityBreakdownByMonthDate
@SOURCEIDS,
@COMPUTERIDS,
@ENDDATE,
@TIMEZONE,
@PERIOD,
@AVERAGEINTERVAL,
@GROUPBY,
@THRESHOLD,
@PROBLEM,
@PMSTATUS
ELSE
exec APM.ApplicationStatusDrillthrough
@SOURCEIDS,
@COMPUTERIDS,
@ENDDATE,
@TIMEZONE,
@PERIOD,
@AVERAGEINTERVAL,
@GROUPBY,
@THRESHOLD,
@PROBLEM,
@PMSTATUS
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.SummaryUserAnalysisCSM'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.SummaryUserAnalysisCSM AS RETURN 1')
END
GO

/************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME:SummaryUserAnalysisCSM */
/* USED IN: Summary User Analysis Report - summary table */
/* INPUT PARAMETERS: */
/* @STARTDATE - Start date of the priod */
/* @ENDDATE - End date of the period */
/* @SOURCEIDS - List of source Id, separated by comma. Exp: '1,2,3' */
/* @MACHINEIDS - List of machine Id, separated by comma. Exp: '4,5,6' */
/* @INCLUDESUBNET - Subnet masks list, which should be included */
/* @EXCLUDESUBNET - Subnet mask list, which should be excluded */
/* @ORDERBY - Specifies column ordering should be applied */
/* 1 - EventCount */
/* 2 - ProblemCount */
/* 3 - PerformanceEventCount */
/* 4 - ExceptionEventCount */
/* 5 - MaxTotalTime */
/* 6 - TotalTime */
/* 7 - MaxTotalSize */
/* 8 - TotalSize */
/************************************************************************************/
/* This stored procedure returns top 10 users ordered by user defined input */
/* parameter @ORDERBY. Every user have exactly five records of data with top five */
/* page,java script and ajax, exception events ordered by events count of each */
/* specific event. */
/* Each record is also contains overall statistics for the Summary table and */
/* charts. */
/************************************************************************************/
alter PROCEDURE [APM].[SummaryUserAnalysisCSM]
@STARTDATE DATETIME,
@ENDDATE DATETIME,
@SOURCEIDS NVARCHAR(MAX),
@MACHINEIDS NVARCHAR(MAX),
@INCLUDESUBNET NVARCHAR(MAX),
@EXCLUDESUBNET NVARCHAR(MAX),
@THRESHOLD DECIMAL(35,0),
@ORDERBY INT,
@PMSTATUS NVARCHAR(50)
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON

SELECT
@INCLUDESUBNET = REPLACE(@INCLUDESUBNET, N'*', N'%'),
@EXCLUDESUBNET = REPLACE(@EXCLUDESUBNET, N'*', N'%')

-- Filter table, which contains machine ids and source ids
-- typeid defines filter type - 1 for source and 2 for machine
-- valueId filter value - source id and machine id
CREATE TABLE #SOURCEMACHINEFILTERTABLE(
TYPEID INT,
VALUEID INT
)

-- Fill table #SOURCEMACHINEFILTERTABLE
INSERT INTO #SOURCEMACHINEFILTERTABLE
SELECT
p.typeId AS TYPEID,
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@SOURCEIDS, @MACHINEIDS) AS p

-- Filter table, which contains PM Statuses of Events
CREATE TABLE #PMSTATUSFILTERTABLE(
VALUEID INT
)

-- Fill table #PMSTATUSFILTERTABLE
INSERT
INTO #PMSTATUSFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@PMSTATUS, N'') AS p

-- Filter table for SubnetC values
CREATE TABLE #SUBNETCFILTERTABLE
(
IPID INT,
SUBNETC NVARCHAR(50) collate database_default
)

-- Insert into filter id of the SubnetC to increase performence for event table
INSERT INTO #SUBNETCFILTERTABLE
SELECT DISTINCT
ipid,
ip.SubNetC
FROM
apm.IP AS ip (NOLOCK)
JOIN APM.GetMultiParameters(CASE WHEN LEN(@INCLUDESUBNET) &gt; 0 THEN @INCLUDESUBNET ELSE N'%' END, N'') AS p1 ON (ip.SubnetC LIKE p1.Value)
LEFT OUTER JOIN APM.GetMultiParameters(CASE WHEN LEN(@EXCLUDESUBNET) &gt; 0 THEN @EXCLUDESUBNET ELSE N'Fake' END, N'') AS p2 ON (ip.SubnetC LIKE p2.Value)
WHERE
--Exclude subnets which have correspondance in @EXCLUDESUBNET parameter
p2.typeId IS NULL


/*************************************************** Main Query ***************************************************/

-- Calculating information about Page events
;WITH PageEvents AS
(
SELECT
NULL AS classType,
ROW_NUMBER() OVER(PARTITION BY UserId ORDER BY COUNT(CSEventId) DESC, PageUri ASC) AS RowId,
PageUri,
UserId,
COUNT(CSEventId) AS EventCount,
COUNT(DISTINCT CSEventGroup) AS ProblemCount,
AVG(NetworkTime) AS NetworkTime,
AVG(ServerTime) AS ServerTime,
AVG(DOMTime) AS DOMTime,
AVG(PeripheralTime) AS PeripheralTime,
AVG(OnLoadTime) AS OnLoadTime,
AVG(TotalTime) AS TotalTime,
AVG(TotalSize) AS TotalSize,
-- This value is needed for ordering by maximum total time in the summary table
MAX(MAX(TotalTime)) OVER(PARTITION BY UserId) AS MaxTotalTime,
-- These values are needed to calculate average event duration and average size for user
SUM(SUM(TotalTime)) OVER(PARTITION BY UserId) AS UserSumTime,
SUM(SUM(TotalSize)) OVER(PARTITION BY UserId) AS UserSumSize,
-- This value is page event count for current user
SUM(COUNT(*)) OVER(PARTITION BY UserId) AS UserPageEventCount,
-- These values are needed to calculate average times for current page (information for "all" chart)
SUM(COUNT(*)) OVER(PARTITION BY PageUri) AS SamePageEventCount,
SUM(SUM(NetworkTime)) OVER(PARTITION BY PageUri) AS AvgPageNetworkTime,
SUM(SUM(ServerTime)) OVER(PARTITION BY PageUri) AS AvgPageServerTime,
SUM(SUM(DOMTime)) OVER(PARTITION BY PageUri) AS AvgPageDOMTime,
SUM(SUM(PeripheralTime)) OVER(PARTITION BY PageUri) AS AvgPagePeripheralTime,
SUM(SUM(OnLoadTime)) OVER(PARTITION BY PageUri) AS AvgPageOnLoadTime,
COUNT(UserId) OVER(PARTITION BY PageUri) AS AffectedUserCount
FROM
(
SELECT
e.CSEventId,
MAX(e.PageUri) AS PageUri,
MAX(e.UserId) AS UserId,
MAX(e.CSEventGroupId) AS CSEventGroup,
MAX(COALESCE(p.NetworkTime,0))/1000 AS NetworkTime,
MAX(COALESCE(p.ServerTime,0))/1000 AS ServerTime,
MAX(COALESCE(p.DOMTime,0))/1000 AS DOMTime,
MAX(COALESCE(p.PeripheralTime,0))/1000 AS PeripheralTime,
MAX(COALESCE(p.OnLoadTime,0))/1000 AS OnLoadTime,
MAX(p.TotalTime)/1000 AS TotalTime,
MAX(COALESCE(CAST(p.TotalSize AS DECIMAL(35,2)),0))/1024 + SUM(COALESCE(CAST(a.ResponseSize AS DECIMAL(35,2)),0) + COALESCE(CAST(a.REQUESTSIZE AS DECIMAL(35,2)),0))/1024 AS TotalSize
FROM
apm.CSEvent AS e (NOLOCK)
JOIN #SOURCEMACHINEFILTERTABLE AS f1 ON (f1.VALUEID = e.SourceId AND f1.TYPEID = 1)
JOIN #SOURCEMACHINEFILTERTABLE AS f2 ON (f2.VALUEID = e.MachineId AND f2.TYPEID = 2)
JOIN #SUBNETCFILTERTABLE AS f3 ON e.ipid = f3.IPID
JOIN #PMSTATUSFILTERTABLE AS f4 ON (f4.VALUEID = e.PMStatus)
JOIN apm.CSPageEvent AS p (NOLOCK) ON e.CSEventId = p.CSEventId
LEFT OUTER JOIN apm.CSAjax AS a (NOLOCK) ON e.CSEventId = a.CSEventId
WHERE
e.UTCDate &gt;= @STARTDATE
AND e.UTCDate &lt; @ENDDATE
AND e.UserId IS NOT NULL
AND e.PageUri IS NOT NULL
AND p.TotalTime/1000.0 &gt;= @THRESHOLD
GROUP BY
E.CSEventId /* Grouping by Id of the specific event to be able to
summarize data of page event with Ajax ones which
were generated by it. */
) AS pe
GROUP BY
PageUri,
UserId
),
-- Calculating information about Java script and Ajax events
JSandAjaxEvents AS
(
SELECT
classType,
ROW_NUMBER() OVER(PARTITION BY UserId ORDER BY COUNT(EventId) DESC, PageUri, [Action] ASC) AS RowId,
UserId,
PageUri,
[Action],
COUNT(*) AS EventCount,
COUNT(DISTINCT EventGroupId) AS ProblemCount,
AVG(NetworkTime) AS NetworkTime,
AVG(ServerTime) AS ServerTime,
AVG(TotalTime - NetworkTime - ServerTime) AS ClientTime,
AVG(TotalTime) AS TotalTime,
-- This value is needed for ordering by maximum total time in the summary table
MAX(MAX(TotalTime)) OVER(PARTITION BY UserId) AS MaxTotalTime,
AVG(TotalSize) AS TotalSize,
SUM(SUM(TotalSize)) OVER(PARTITION BY UserId) AS UserSumSize,
SUM(SUM(NetworkTime)) OVER(PARTITION BY PageUri,[Action]) AS AllNetworkTime,
SUM(SUM(ServerTime)) OVER(PARTITION BY PageUri,[Action]) AS AllServerTime,
SUM(SUM(TotalTime - NetworkTime - ServerTime)) OVER(PARTITION BY PageUri,[Action]) AS AllClientTime,
SUM(SUM(TotalTime)) OVER(PARTITION BY PageUri,[Action]) AS AllTotalTime,
SUM(SUM(TotalTime)) OVER(PARTITION BY UserId) AS UserSumTime,
COUNT(UserId) OVER(PARTITION BY PageUri,[Action]) AS AffectedUserCount,
SUM(COUNT(*)) OVER(PARTITION BY UserId) AS TotalUserEventCount,
SUM(COUNT(*)) OVER(PARTITION BY PageUri,[Action]) AS TotalPageEventCount
FROM
(
SELECT
MAX(CASE WHEN COALESCE(a.Synchronous,1) = 0 THEN 1 ELSE 2 END) AS classType,
e.CSEventId AS EventId,
MAX(e.UserId) AS UserId,
MAX(e.CSEventGroupId) AS EventGroupId,
MAX(e.PageUri) AS PageUri,
MAX(CASE WHEN COALESCE(a.Synchronous,1) = 0 THEN a.Uri ELSE j.Action END) AS [Action],
SUM((COALESCE(a.NetworkTime,0) + COALESCE(a.ResponseTime,0))/1000) AS NetworkTime,
SUM(COALESCE(a.ServerTime,0))/1000 AS ServerTime,
MAX(COALESCE(j.TotalTime, a.TotalTime))/1000 AS TotalTime,
CAST(SUM(COALESCE(a.REQUESTSIZE,0) + COALESCE(a.ResponseSize,0)) AS DECIMAL(35,2))/1024 AS TotalSize
FROM
apm.CSEvent (NOLOCK) as e
JOIN #SOURCEMACHINEFILTERTABLE AS f1 ON (f1.VALUEID = e.SourceId AND f1.TYPEID = 1)
JOIN #SOURCEMACHINEFILTERTABLE AS f2 ON (f2.VALUEID = e.MachineId AND f2.TYPEID = 2)
JOIN #SUBNETCFILTERTABLE AS f3 ON e.ipid = f3.IPID
JOIN #PMSTATUSFILTERTABLE AS f4 ON (f4.VALUEID = e.PMStatus)
LEFT OUTER JOIN apm.CSJScriptEvent AS j ON e.CSEventId = j.CSEventId
LEFT OUTER JOIN apm.CSAjax AS a ON e.CSEventId = a.CSEventId
WHERE
e.UTCDate &gt;= @STARTDATE
AND e.UTCDate &lt; @ENDDATE
AND e.UserId IS NOT NULL
AND e.PageUri IS NOT NULL
AND e.EventClass &lt;&gt; N'CSMPMonitorLog'
AND e.CLassType = N'performance'
AND COALESCE(j.TotalTime, a.TotalTime)/1000.0 &gt;= @THRESHOLD
GROUP BY
e.CSEventId
) AS jsax
GROUP BY
jsax.UserId,
jsax.PageUri,
jsax.Action,
jsax.classType
),
-- Prepairing template in which every user will have exactly five rows for top page, exceptionevents
PreResultTemplate AS
(
SELECT
UserId
FROM
apm.CSEvent (NOLOCK) AS e
JOIN #SOURCEMACHINEFILTERTABLE AS f1 ON (f1.VALUEID = e.SourceId AND f1.TYPEID = 1)
JOIN #SOURCEMACHINEFILTERTABLE AS f2 ON (f2.VALUEID = e.MachineId AND f2.TYPEID = 2)
JOIN #SUBNETCFILTERTABLE AS f3 ON e.ipid = f3.IPID
JOIN #PMSTATUSFILTERTABLE AS f4 ON (f4.VALUEID = e.PMStatus)
WHERE
UTCDate &gt;= @STARTDATE
AND UTCDate &lt; @ENDDATE
AND PageUri IS NOT NULL
AND UserId IS NOT NULL
GROUP BY
UserId
),
ResultTemplate AS -- Template which has exactly 5 rows for each user
(
SELECT
pr.UserId,
n.n AS RowId
FROM
PreResultTemplate as pr
CROSS JOIN APM.fn_numS(5) AS n
),
-- Calculating information about Exception events
ExceptionEvents AS
(
SELECT
4 AS classType,
ROW_NUMBER() OVER(PARTITION BY UserId ORDER BY COUNT(CSEventId) DESC, [Description] ASC) AS RowId,
UserId,
Description,
COUNT(CSEventId) AS EventCount,
COUNT(DISTINCT CSEventGroupId) AS ProblemCount,
COUNT(CASE WHEN CHARINDEX(N'MSIE', E.Browser) &gt; 0 THEN E.CSEventId END) AS IEEventCount,
COUNT(CASE WHEN CHARINDEX(N'Firefox', E.Browser) &gt; 0 THEN E.CSEventId END) AS FirefoxEventCount,
AVG(COUNT(CSEventId)*1.0) OVER(PARTITION BY [Description]) AS AllEventCount,
AVG(COUNT(CASE WHEN CHARINDEX(N'MSIE', E.Browser) &gt; 0 THEN E.CSEventId END)*1.0) OVER(PARTITION BY [Description]) AS AllIEEventCount,
AVG(COUNT(CASE WHEN CHARINDEX(N'Firefox', E.Browser) &gt; 0 THEN E.CSEventId END)*1.0) OVER(PARTITION BY [Description]) AS AllFirefoxEventCount,
COUNT(UserId) OVER(PARTITION BY [Description]) AS AffectedUserCount,
SUM(COUNT(CSEventId)) OVER(PARTITION BY UserId) AS UserEventCount
FROM
apm.CSEvent (NOLOCK) AS e
JOIN #SOURCEMACHINEFILTERTABLE AS f1 ON (f1.VALUEID = e.SourceId AND f1.TYPEID = 1)
JOIN #SOURCEMACHINEFILTERTABLE AS f2 ON (f2.VALUEID = e.MachineId AND f2.TYPEID = 2)
JOIN #SUBNETCFILTERTABLE AS f3 ON e.ipid = f3.IPID
JOIN #PMSTATUSFILTERTABLE AS f4 ON (f4.VALUEID = e.PMStatus)
WHERE
e.UTCDate &gt;= @STARTDATE
AND e.UTCDate &lt; @ENDDATE
AND e.UserId IS NOT NULL
AND e.PageUri IS NOT NULL
AND e.ClassType = N'exception'
GROUP BY
UserId,
[Description]
),
-- Summarizing data from PageEvents, ExceptionEvents and JSandAjaxEvents CTE's
ResultTable AS
(
SELECT
/* Create additional field to have an ability to sort out the unusual events when
creating URLs*/
js.classType,
/* Create additional field for sorting according to the @ORDERBY input parameter.
Selecting maximum value of selected field for each user. */
CASE @ORDERBY
WHEN 1 THEN MAX(COALESCE(ex.UserEventCount,0) + COALESCE(pg.UserPageEventCount,0) + COALESCE(js.TotalUserEventCount,0)) OVER(PARTITION BY rt.UserId)
WHEN 2 THEN SUM(COALESCE(ex.ProblemCount,0) + COALESCE(pg.ProblemCount,0) + COALESCE(js.ProblemCount,0)) OVER(PARTITION BY rt.UserId)
WHEN 3 THEN MAX(COALESCE(pg.EventCount,0)) OVER(PARTITION BY rt.UserId)
WHEN 4 THEN MAX(COALESCE(ex.EventCount,0)) OVER(PARTITION BY rt.UserId)
-- Choosing the maximum value from the page and javascript event
WHEN 5 THEN
MAX(CASE WHEN COALESCE(pg.MaxTotalTime,0) &gt;= COALESCE(js.MaxTotalTime,0)
THEN COALESCE(pg.MaxTotalTime,0)
ELSE COALESCE(js.MaxTotalTime,0)
END) OVER(PARTITION BY rt.UserId)
-- Caculating average user page, ajax and javascript event time
WHEN 6 THEN
(CASE WHEN (MAX(COALESCE(pg.UserPageEventCount,0) + COALESCE(js.TotalUserEventCount,0))OVER(PARTITION BY rt.UserId)) &gt; 0
THEN (MAX(COALESCE(pg.UserSumTime,0) + COALESCE(js.UserSumTime,0)) OVER(PARTITION BY rt.UserId))/(MAX(COALESCE(pg.UserPageEventCount,0) + COALESCE(js.TotalUserEventCount,0)) OVER(PARTITION BY rt.UserId))
ELSE 0
END)
-- Calculating average user page, ajax and javascript event size
WHEN 7 THEN
(CASE WHEN (MAX(COALESCE(pg.UserPageEventCount,0) + COALESCE(js.TotalUserEventCount,0)) OVER(PARTITION BY rt.UserId))&gt; 0
THEN (MAX(COALESCE(pg.UserSumSize,0) + COALESCE(js.UserSumSize,0)) OVER(PARTITION BY rt.UserId))/(max(COALESCE(pg.UserPageEventCount,0)+COALESCE(js.TotalUserEventCount,0))OVER(PARTITION BY rt.UserId))
ELSE 0
END)
END AS OrderData,
rt.RowId,
rt.UserId,
(CASE WHEN (MAX(COALESCE(pg.UserPageEventCount,0) + COALESCE(js.TotalUserEventCount,0)) OVER(PARTITION BY rt.UserId))&gt; 0
THEN (MAX(COALESCE(pg.UserSumSize,0) + COALESCE(js.UserSumSize,0)) OVER(PARTITION BY rt.UserId))/(max(COALESCE(pg.UserPageEventCount,0)+COALESCE(js.TotalUserEventCount,0))OVER(PARTITION BY rt.UserId))
ELSE 0
END) AS UserAvgSize,
(CASE WHEN (MAX(COALESCE(pg.UserPageEventCount,0) + COALESCE(js.TotalUserEventCount,0))OVER(PARTITION BY rt.UserId)) &gt; 0
THEN (MAX(COALESCE(pg.UserSumTime,0) + COALESCE(js.UserSumTime,0)) OVER(PARTITION BY rt.UserId))/(MAX(COALESCE(pg.UserPageEventCount,0) + COALESCE(js.TotalUserEventCount,0)) OVER(PARTITION BY rt.UserId))
ELSE 0
END) AS UserAvgTime,
-- Summarize problems count between all issues as this information is shown in summary table for user
SUM(COALESCE(ex.ProblemCount,0) + COALESCE(pg.ProblemCount,0) + COALESCE(js.ProblemCount,0)) OVER(PARTITION BY rt.UserId) AS ProblemCount,
MAX((COALESCE(ex.UserEventCount,0) + COALESCE(pg.UserPageEventCount,0) + COALESCE(js.TotalUserEventCount,0))) OVER(PARTITION BY rt.UserId) AS EventCount,
-- Exception events details --
(ex.Description) AS Ex_Description,
(ex.EventCount) AS Ex_EventCount,
(ex.IEEventCount) AS Ex_IEEventCount,
(ex.FireFoxEventCount) AS Ex_FireFoxEventCount,
(ex.AllEventCount) AS Ex_AllEventCount,
(ex.AllIEEventCount) AS Ex_AllIEEventCount,
(ex.AllFirefoxEventCount) AS Ex_AllFirefoxEventCount,
(ex.AffectedUserCount) AS Ex_AffectedUserCount,
MAX(COALESCE(ex.UserEventCount,0)) OVER(PARTITION BY rt.UserId) AS Ex_UserEventCount,
-- Page events details --
(pg.PageUri) AS Pg_PageUri,
(pg.MaxTotalTime) AS Pg_MaxTotalTime,
(pg.EventCount) AS Pg_EventCount,
(pg.NetworkTime) AS Pg_NetworkTime,
(pg.ServerTime) AS Pg_ServerTime,
(pg.DOMTime) AS Pg_DOMTime,
(pg.PeripheralTime) AS Pg_PeripheralTime,
(pg.OnLoadTime) AS Pg_OnLoadTime,
(pg.TotalTime) AS Pg_TotalTime,
(pg.TotalSize) AS Pg_TotalSize,
(pg.AvgPageNetworkTime / pg.SamePageEventCount) AS Pg_AvgPageNetworkTime,
(pg.AvgPageServerTime / pg.SamePageEventCount) AS Pg_AvgPageServerTime,
(pg.AvgPageDOMTime / pg.SamePageEventCount) AS Pg_AvgPageDOMTime,
(pg.AvgPagePeripheralTime / pg.SamePageEventCount) AS Pg_AvgPagePeripheralTime,
(pg.AvgPageOnLoadTime / pg.SamePageEventCount) AS Pg_AvgPageOnLoadTime,
(pg.AffectedUserCount) AS Pg_AffectedUserCount,
(pg.UserSumTime / pg.UserPageEventCount) AS Pg_AvgUserTime,
(pg.UserSumSize / pg.UserPageEventCount) AS Pg_AvgUserSize,
MAX(pg.UserPageEventCount) OVER(PARTITION BY rt.UserId) AS Pg_UserPageEventCount,
-- Javascript and Ajax events details --
(js.PageUri) AS Js_PageUri,
(js.Action) AS Js_Action,
(js.MaxTotalTime) AS Js_MaxTotalTime,
(js.EventCount) AS Js_EventCount,
(js.NetworkTime) AS Js_NetworkTime,
(js.ServerTime) AS Js_ServerTime,
(js.ClientTime) AS Js_ClientTime,
(js.TotalTime) AS Js_TotalTime,
(js.TotalSize) AS Js_TotalSize,
(js.AllNetworkTime / js.TotalPageEventCount) AS Js_AllNetworkTime,
(js.AllServerTime / js.TotalPageEventCount) AS Js_AllServerTime,
(js.AllClientTime / js.TotalPageEventCount) AS Js_AllClientTime,
(js.AllTotalTime / js.TotalPageEventCount) AS Js_AllTotalTime,
js.AffectedUserCount AS Js_AffectedUserCount,
MAX(COALESCE(js.TotalUserEventCount,0)) OVER(PARTITION BY rt.UserId) AS Js_TotalUserEventCount
FROM
ResultTemplate AS rt
LEFT OUTER JOIN ExceptionEvents AS ex ON ex.UserId = rt.UserId AND ex.RowId = rt.RowId
LEFT OUTER JOIN PageEvents AS pg ON pg.UserId = rt.UserId AND pg.RowId = rt.RowId
LEFT OUTER JOIN JSandAjaxEvents AS js ON js.UserId = rt.UserId AND js.RowId = rt.RowId
)
SELECT
TOP 50
res.classType,
res.OrderData, -- As we have exactly 5 rows for each user, we select the first ten of them.
res.RowId,
u.Name,
res.ProblemCount,
res.EventCount,
res.UserAvgSize,
res.UserAvgTime,
res.Ex_Description,
res.Ex_EventCount,
res.Ex_IEEventCount,
res.Ex_FireFoxEventCount,
res.Ex_AllEventCount,
res.Ex_AllIEEventCount,
res.Ex_AllFirefoxEventCount,
res.Ex_AffectedUserCount,
res.Ex_UserEventCount,
res.Pg_PageUri,
res.Pg_MaxTotalTime,
res.Pg_EventCount,
res.Pg_NetworkTime,
res.Pg_ServerTime,
res.Pg_DOMTime,
res.Pg_PeripheralTime,
res.Pg_OnLoadTime,
res.Pg_TotalTime,
res.Pg_TotalSize,
res.Pg_AvgPageNetworkTime,
res.Pg_AvgPageServerTime,
res.Pg_AvgPageDOMTime,
res.Pg_AvgPagePeripheralTime,
res.Pg_AvgPageOnLoadTime,
res.Pg_AffectedUserCount,
res.Pg_AvgUserTime,
res.Pg_AvgUserSize,
res.Pg_UserPageEventCount,
res.Js_PageUri,
res.Js_Action,
res.Js_MaxTotalTime,
res.Js_EventCount,
res.Js_NetworkTime,
res.Js_ServerTime,
res.Js_ClientTime,
res.Js_TotalTime,
res.Js_TotalSize,
res.Js_AllNetworkTime,
res.Js_AllServerTime,
res.Js_AllClientTime,
res.Js_AllTotalTime,
res.Js_AffectedUserCount,
res.Js_TotalUserEventCount
FROM
ResultTable AS res
JOIN apm.Users AS u ON u.UserId = res.UserId
WHERE
-- This condition is set as users where not filtered by threshold, and ther could be situations when there is no events at all
-- for some user. Such users should not be selected. It wouldn't have affect on ordering as for such users all other values is 0
res.EventCount &gt; 0
ORDER BY
res.OrderData DESC,u.Name,res.Rowid
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.PCType_ConfigSync'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.PCType_ConfigSync AS RETURN 1')
END
GO


/****************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: PCType_ConfigSync */
/* USED IN: transfer routine : task=ConfigSynchronization;action=SyncPerfCountersAction */
/* DESCRIPTION: updates INSTANCEFUNCTION, DATEFUNCTION for counters, that are listed */
/* in configuration file */
/* INPUT PARAMETERS: */
/* @DESCRIPTORS - List of counters in XML format (aggregation/perfcounterSet */
/* @TRACELEVEL - service variable (error tracing level) */
/****************************************************************************************/
alter PROCEDURE APM.PCType_ConfigSync
@DESCRIPTORS NTEXT
,@TRACELEVEL INT
AS
BEGIN
SET NOCOUNT ON

DECLARE
@ERRORIND BIT
,@ERRORMESSAGE NVARCHAR(MAX)
,@ERRORNUMBER INT
,@ERRORSEVERITY INT
,@ERRORSTATE INT
,@ERRORLINE INT
,@ERRORPROCEDURE NVARCHAR(256)
,@ERRORMESSAGETEXT NVARCHAR(MAX)

BEGIN TRY

DECLARE @EXECRESULT INT
DECLARE @ROWCOUNT INT
DECLARE @HANDLER INT

-- Prepare xml document
EXEC SP_XML_PREPAREDOCUMENT @HANDLER OUTPUT, @DESCRIPTORS
IF @EXECRESULT &lt;&gt; 0
BEGIN
SELECT @ERRORMESSAGE = message FROM APM.messages WHERE id = 50002
RAISERROR(@ERRORMESSAGE, 16, 1, 'PCType_ConfigSync', @EXECRESULT)
END

-- Create temporary table for counters
CREATE TABLE #DESCRIPTORSET (
DESCRIPTOR NVARCHAR(255) collate database_default NOT NULL,
INSTANCEFUNCTION NVARCHAR(50) collate database_default NOT NULL,
DATEFUNCTION NVARCHAR(50) collate database_default NOT NULL
)

-- Fill table with date from xml
INSERT INTO #DESCRIPTORSET
SELECT NAME, COALESCE(INSTANCEFUNC,'AVG'), COALESCE(DATEFUNC,'AVG')
FROM OPENXML (@HANDLER, '/perfcounterSet/perfcounter', 1)
WITH (NAME NVARCHAR(255), INSTANCEFUNC NVARCHAR(50) , DATEFUNC NVARCHAR(50))
SET @ROWCOUNT = @@ROWCOUNT

EXEC SP_XML_REMOVEDOCUMENT @HANDLER

-- Update PCTYPE table with new aggregate function values
UPDATE T
SET T.INSTANCEFUNCTION = sync.INSTANCEFUNCTION,
T.DATEFUNCTION = sync.DATEFUNCTION
FROM apm.PCTYPE T
JOIN #DESCRIPTORSET sync ON sync.DESCRIPTOR = T.TYPE

END TRY
BEGIN CATCH
IF (@@TRANCOUNT &gt; 0)
ROLLBACK TRAN

SELECT
@ERRORNUMBER = ERROR_NUMBER()
,@ERRORSEVERITY = ERROR_SEVERITY()
,@ERRORSTATE = ERROR_STATE()
,@ERRORLINE = ERROR_LINE()
,@ERRORPROCEDURE = ISNULL(ERROR_PROCEDURE(), '-')
,@ERRORMESSAGETEXT = ERROR_MESSAGE()
SET @ERRORIND = 1
END CATCH

-- report error if any
IF (@ERRORIND = 1)
BEGIN
DECLARE @ADJUSTEDERRORSEVERITY int

SET @ADJUSTEDERRORSEVERITY = CASE
WHEN @ERRORSEVERITY = 2601 OR @ERRORSEVERITY = 2627 THEN 0
WHEN @ERRORSEVERITY &gt; 18 THEN 18
ELSE @ERRORSEVERITY
END

SELECT @ERRORMESSAGE = message FROM APM.Messages WHERE id = 50004
RAISERROR (@ERRORMESSAGE
,@ADJUSTEDERRORSEVERITY
,1
,@ERRORNUMBER
,@ERRORSEVERITY
,@ERRORSTATE
,@ERRORPROCEDURE
,@ERRORLINE
,@ERRORMESSAGETEXT
)
END
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.DeleteEventsOrEventGroups'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.DeleteEventsOrEventGroups AS RETURN 1')
END
GO


/****************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: DeleteEventsOrEventGroups */
/* DESCRIPTION: */
/* Delete events using #EVENTGROOM(eventid) table or delete eventgroup that hot have */
/* events and older @LASTKEEPDATE. Events will be delete if #EVENTGROOM table is not */
/* empty otherwise event groups will be deleted */
/* INPUT PARAMETERS: */
/* @ROWSPERITERATION - number of records that have been deleted by one delete */
/* instruction */
/* @CLIENT - 1:client events 0:server events */
/* @LASTKEEPDATE - last keep date. It use for delete event groups */
/* OUTPUT PARAMETERS: */
/* @ROWSAFFECTED - Number of deleted events or event groups */
/****************************************************************************************/
alter PROCEDURE APM.DeleteEventsOrEventGroups
@ROWSPERITERATION int
,@CLIENT bit
,@LASTKEEPDATE datetime
,@ROWSAFFECTED int OUTPUT
AS
SET @ROWSAFFECTED = 0
IF @CLIENT = 0
BEGIN
--delete server events
IF EXISTS(SELECT * FROM #EVENTGROOM)
BEGIN
--- Grooming performance node ---------
DELETE pn
FROM APM.PerformanceNode AS pn
JOIN #EVENTGROOM AS eventFilter ON pn.eventid = eventFilter.EVENTID

--- Grooming resource group node ---------
DELETE rgn
FROM APM.ResourceGroupNode AS rgn
JOIN #EVENTGROOM AS eventFilter ON rgn.eventid = eventFilter.EVENTID

--- Grooming exception node ---------
DELETE en
FROM APM.ExceptionNode AS en
JOIN #EVENTGROOM AS eventFilter ON en.eventid = eventFilter.EVENTID

-- Grooming server detail events ---
DELETE ed
FROM APM.eventdetail AS ed
JOIN #EVENTGROOM AS eventFilter ON ed.eventid = eventFilter.EVENTID

DELETE e
FROM APM.Event AS e
JOIN #EVENTGROOM AS eventFilter ON e.eventid = eventFilter.EVENTID

SELECT @ROWSAFFECTED = @@ROWCOUNT
END
ELSE
BEGIN
-- delete server event groups
WHILE EXISTS (SELECT * FROM APM.EventGroup G
WHERE G.LASTEVENTDATE &lt; @LASTKEEPDATE
AND NOT EXISTS(SELECT * FROM EVENT e WHERE e.eventgroupId = G.EventGroupId)
)
BEGIN
DELETE TOP (@ROWSPERITERATION) g
FROM APM.EventGroup AS g
WHERE G.LASTEVENTDATE &lt; @LASTKEEPDATE
AND NOT EXISTS(SELECT * FROM EVENT e WHERE e.eventgroupId = G.EventGroupId)

SELECT @ROWSAFFECTED = @ROWSAFFECTED + @@ROWCOUNT
END
END
END
IF @CLIENT = 1
BEGIN
-- delete client events
IF EXISTS(SELECT * FROM #EVENTGROOM)
BEGIN
-- Grooming PageEvent-----
DELETE pe
FROM APM.cspageevent AS pe
JOIN #EVENTGROOM AS eventFilter ON pe.cseventid = eventFilter.EVENTID

-- Grooming Peripheral Details -----
DELETE pd
FROM APM.csperipheraldetail AS pd
JOIN APM.csperipheral AS pe ON pe.csperipheralId = pd.csperipheralId
JOIN #EVENTGROOM AS eventFilter ON pe.cseventid = eventFilter.EVENTID

-- Grooming Peripheral ------
DELETE pe
FROM APM.csperipheral AS pe
JOIN #EVENTGROOM AS eventFilter ON pe.cseventid = eventFilter.EVENTID

-- Grooming csHeaviestResource ---
DELETE hr
FROM APM.csHeaviestResource AS hr
JOIN #EVENTGROOM AS eventFilter ON hr.cseventid = eventFilter.EVENTID

-- Grooming ajax events ---
DELETE aj
FROM APM.csAjax AS aj
JOIN #EVENTGROOM AS eventFilter ON aj.cseventid = eventFilter.EVENTID

-- Grooming async ajax events ---
DELETE aj
FROM APM.csAsyncAjax AS aj
JOIN #EVENTGROOM AS eventFilter ON aj.cseventid = eventFilter.EVENTID

-- Grooming async jscript events ---
DELETE js
FROM APM.csJScriptEvent AS js
JOIN #EVENTGROOM AS eventFilter ON js.cseventid = eventFilter.EVENTID

-- Grooming client exception events ---
DELETE ex
FROM APM.csexevent AS ex
JOIN #EVENTGROOM AS eventFilter ON ex.cseventid = eventFilter.EVENTID

-- Grooming client detail events ---
DELETE ed
FROM APM.cseventdetail AS ed
JOIN #EVENTGROOM AS eventFilter ON ed.cseventid = eventFilter.EVENTID

-- Grooming client events ---
DELETE ev
FROM APM.csEvent ev
JOIN #EVENTGROOM AS eventFilter ON ev.cseventid = eventFilter.EVENTID

SELECT @ROWSAFFECTED = @@ROWCOUNT
END
ELSE
BEGIN
--delete client groups
WHILE EXISTS (SELECT * FROM APM.csEventGroup g
WHERE g.lasteventdate &lt; @LASTKEEPDATE
AND NOT EXISTS(SELECT * FROM csEvent e WHERE e.cseventgroupId = g.csEventGroupId)
)
BEGIN
DELETE TOP (@ROWSPERITERATION) g
FROM APM.csEventGroup AS g
WHERE g.lasteventdate &lt; @LASTKEEPDATE
AND NOT EXISTS(SELECT * FROM csEVENT e WHERE e.cseventgroupId = g.csEventGroupId)

SELECT @ROWSAFFECTED = @ROWSAFFECTED + @@ROWCOUNT
END
END
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.ExtractEventGroomingRows'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.ExtractEventGroomingRows AS RETURN 1')
END
GO
/****************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: ExtractEventGroomingRows */
/* DESCRIPTION: */
/* It fill #EVENTGROOM(eventid) table from server or client events by date and status */
/* INPUT PARAMETERS: */
/* @ROWSPERITERATION - number of records that have been selected from underline table */
/* @LASTKEEPDATE - last keep date. */
/* @DATABASEID - database primary key from seviewerdb table */
/* @CLIENT - 1:client events 0:server events */
/* @PMSTATUS - problem management */
/****************************************************************************************/
alter PROCEDURE [APM].[ExtractEventGroomingRows]
@ROWSPERITERATION int
,@LASTKEEPDATE datetime
,@DATABASEID int
,@CLIENT bit
,@PMSTATUS tinyint
AS
SET NOCOUNT ON

IF @CLIENT = 0
BEGIN
--server events
IF @PMSTATUS IS null
INSERT #EVENTGROOM
SELECT TOP(@ROWSPERITERATION) e.EventId
FROM APM.event (NOLOCK) AS e
WHERE
e.SEVIEWERDBID = @DATABASEID AND
e.UTCEVENTDATE &lt; @LASTKEEPDATE
ELSE
INSERT #EVENTGROOM
SELECT TOP(@ROWSPERITERATION) e.EventId
FROM APM.EVENT (NOLOCK) E
JOIN apm.PMSERVEREVENTTRACE (NOLOCK) ET ON E.EVENTID = ET.EVENTID
JOIN apm.PMTRACE PT (NOLOCK) ON PT.PMTRACEID = ET.PMTRACEID
WHERE
e.PMSTATUS = @PMSTATUS AND
e.UTCEVENTDATE &lt; @LASTKEEPDATE AND
e.SEVIEWERDBID = @DATABASEID
GROUP BY
E.EVENTID
HAVING
MAX(PT.UTCDATE) &lt; @LASTKEEPDATE
ORDER BY
E.EVENTID ASC

END
ELSE
BEGIN
--client events
IF @PMSTATUS IS null
INSERT #EVENTGROOM
SELECT TOP(@ROWSPERITERATION) e.cseventId
FROM APM.csevent (NOLOCK) AS e
WHERE
e.SEVIEWERDBID = @DATABASEID AND
e.utcDate &lt; @LASTKEEPDATE
ELSE
INSERT #EVENTGROOM
SELECT TOP(@ROWSPERITERATION) e.csEventId
FROM APM.CSEVENT (NOLOCK) E
JOIN apm.PMCLIENTEVENTTRACE (NOLOCK) ET ON E.CSEVENTID = ET.CSEVENTID
JOIN apm.PMTRACE PT (NOLOCK) ON PT.PMTRACEID = ET.PMTRACEID
WHERE
e.PMSTATUS = @PMSTATUS AND
e.utcDate &lt; @LASTKEEPDATE AND
e.SEVIEWERDBID = @DATABASEID
GROUP BY
E.CSEVENTID
HAVING
MAX(PT.UTCDATE) &lt; @LASTKEEPDATE
ORDER BY
E.csEVENTID ASC
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.GroomingWorkTables'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.GroomingWorkTables AS RETURN 1')
END
GO
/* PROCEDURE GROOM SERVER EVENTS, CLIENT EVENTS AND PERFORMANCE COUNTERS. */
/* Description: */
/* The stored proc delete old events and performance counters. It also delete */
/* events with status 'Deleted' or 'By design' using parameters from config table. */
/* INPUT PARAMETERS: */
/* @TABLENAME: */
/* 'Event' - grooming server and client events */
/* 'PerfHourly'- grooming performance counters for the perfhourly table */
/* 'PerfDaily'- grooming performance counters for the perfDaily table */
/* @DATABASEID: database identifier */
/* @RECORDCOUNT: batch record size */
/* @TRACELEVEL: trace level */
alter PROCEDURE [APM].[GroomingWorkTables]
@TABLENAME nvarchar(255),
@RECORDCOUNT INT,
@DATABASEID INT,
@POSTGROOMINGPERIOD INT,
@TRACELEVEL INT
AS
BEGIN
SET NOCOUNT ON;

DECLARE @MESSAGE nvarchar(MAX)
DECLARE @ROWSAFFECTED int
DECLARE @TMPROWSAFFECTED int


DECLARE
@ERRORIND bit
,@ERRORMESSAGE nvarchar(4000)
,@ERRORNUMBER int
,@ERRORSEVERITY int
,@ERRORSTATE int
,@ERRORLINE int
,@ERRORPROCEDURE sysname
,@ERRORMESSAGETEXT nvarchar(4000)

SET @ERRORIND = 0

BEGIN TRY

IF @TRACELEVEL = 4
BEGIN
DECLARE
@PERIODDATESTR nvarchar(20)
SET @PERIODDATESTR = CONVERT(nvarchar(20), DATEADD(Day, -@POSTGROOMINGPERIOD, GETUTCDATE()), 110)
SELECT @MESSAGE = MESSAGE FROM APM.MESSAGES WHERE ID = 50033
RAISERROR (@MESSAGE, 0, 1, @RECORDCOUNT, @POSTGROOMINGPERIOD, @PERIODDATESTR) WITH NOWAIT;
END

CREATE TABLE #EVENTGROOM (
EVENTID BIGINT
)

--clear old events
IF @TABLENAME = N'Event'
BEGIN
-- create event groom settings
DECLARE @EVENTGROOMSETTINGS TABLE
(
id int IDENTITY(1,1)
,configName nvarchar(50) -- configuration parameter
,pmstatus tinyint -- problem management status id
,client bit -- client or server event (1- client, 0 - server)
,defaultLifeTime int -- default life time in hours
)
INSERT @EVENTGROOMSETTINGS(configName, pmstatus, client, defaultLifeTime)
SELECT N'PMLifeTimeInHoursForDeletedEvents' AS configName, 2 AS pmstatus, 0 AS client, 24 AS defaultLifeTime
UNION ALL
SELECT N'PMLifeTimeInHoursForDeletedEvents', 2, 1, 24
UNION ALL
SELECT N'PMLifeTimeInHoursForByDesignEvents', 3, 0, 72
UNION ALL
SELECT N'PMLifeTimeInHoursForByDesignEvents', 3, 1, 72
UNION ALL
SELECT NULL, NULL, 0, NULL
UNION ALL
SELECT NULL, NULL, 1, NULL

DECLARE
@CONFIGNAME nvarchar(50)
,@LASTKEEPDATE datetime
,@CLIENT bit
,@PMSTATUS tinyint
,@LIFETIMEINHOURS int
,@DISPLAYTABLENAME sysname
,@EVENTGROOMSETTINGSID int

-- cycle by event groomsetting
WHILE EXISTS(SELECT * FROM @EVENTGROOMSETTINGS)
BEGIN
--get first settings
SELECT TOP (1)
@EVENTGROOMSETTINGSID = id
,@CONFIGNAME = configName
,@PMSTATUS = pmstatus
,@CLIENT = client
,@LIFETIMEINHOURS = defaultLifeTime
FROM
@EVENTGROOMSETTINGS

--calculate last keep date
SELECT @LASTKEEPDATE = DATEADD(Day, -@POSTGROOMINGPERIOD, GETUTCDATE())
IF @CONFIGNAME IS NOT NULL
BEGIN
SELECT @LIFETIMEINHOURS = CAST(CAST(configvalue AS nvarchar(10)) AS int) FROM APM.CONFIG (NOLOCK)
WHERE configname = @CONFIGNAME
SELECT @LASTKEEPDATE = DATEADD(hh, -@LIFETIMEINHOURS, GETUTCDATE())
END

--trace grooming settings
DECLARE @LASTKEEPDATESTR nvarchar(50)
SELECT @LASTKEEPDATESTR = CONVERT(nvarchar(50), @LASTKEEPDATE, 100)
SELECT @MESSAGE = message FROM APM.MESSAGES (NOLOCK) WHERE id = 50034
RAISERROR (@MESSAGE, 0, 1,
@PMSTATUS, @LIFETIMEINHOURS, @LASTKEEPDATESTR) WITH NOWAIT;

-- execute event grooming
SELECT @ROWSAFFECTED = 0
WHILE 1 = 1
BEGIN
TRUNCATE TABLE #EVENTGROOM
--fill #EVENTGROOM
EXEC APM.ExtractEventGroomingRows
@RECORDCOUNT
,@LASTKEEPDATE
,@DATABASEID
,@CLIENT
,@PMSTATUS
--delete events if #EVENTGROOM is not empty otherwise delete old event groups
EXEC APM.DeleteEventsOrEventGroups
@RECORDCOUNT
,@CLIENT
,@LASTKEEPDATE
,@TMPROWSAFFECTED OUTPUT

IF EXISTS(SELECT * FROM #EVENTGROOM)
-- calculate rows affected
SELECT @ROWSAFFECTED = @TMPROWSAFFECTED + @@ROWCOUNT
ELSE
-- break if #EVENTGROOM is empty
BREAK
END

DELETE @EVENTGROOMSETTINGS WHERE
id = @EVENTGROOMSETTINGSID

----- Trace for events ------
IF @TRACELEVEL = 4
BEGIN
SELECT @DISPLAYTABLENAME = CASE when @CLIENT = 1 THEN N'csEvent' ELSE N'Event' END
SELECT @MESSAGE = MESSAGE FROM APM.MESSAGES WHERE ID = 50023
RAISERROR (@MESSAGE, 0, 1, @ROWSAFFECTED, @DISPLAYTABLENAME) WITH NOWAIT;
END

----- Trace for groups ------
IF @TRACELEVEL = 4
BEGIN
SELECT @DISPLAYTABLENAME = CASE when @CLIENT = 1 THEN N'csEventGroup' ELSE N'EventGroup' END
SELECT @MESSAGE = MESSAGE FROM APM.MESSAGES WHERE ID = 50023
RAISERROR (@MESSAGE, 0, 1, @ROWSAFFECTED, @DISPLAYTABLENAME) WITH NOWAIT;
END
END
END

DROP TABLE #EVENTGROOM

--clear PerfHourly table
IF @TABLENAME = N'PerfHourly'
BEGIN
WHILE EXISTS (SELECT * FROM APM.PerfHourly
WHERE UTCDate &lt; DATEADD(Day, -@POSTGROOMINGPERIOD, GETUTCDATE()))
BEGIN
DELETE TOP(@RECORDCOUNT) FROM APM.PerfHourly
WHERE utcdate &lt; DATEADD(Day, -@POSTGROOMINGPERIOD, GETUTCDATE())
SELECT @ROWSAFFECTED = @ROWSAFFECTED + @@ROWCOUNT
END
IF @TRACELEVEL = 4
BEGIN
SELECT @MESSAGE = MESSAGE FROM APM.MESSAGES WHERE ID = 50023
RAISERROR (@MESSAGE, 0, 1, @ROWSAFFECTED, @TABLENAME) WITH NOWAIT;
END
END

--clear PerfDaily table
IF @TABLENAME = N'PerfDaily'
BEGIN
WHILE EXISTS (SELECT * FROM APM.PerfDaily
WHERE UTCDATE &lt; DATEADD(Day, -@POSTGROOMINGPERIOD, GETUTCDATE()))
BEGIN
DELETE TOP(@RECORDCOUNT) FROM APM.PerfDaily
WHERE UTCDATE &lt; DATEADD(Day, -@POSTGROOMINGPERIOD, GETUTCDATE())
SELECT @ROWSAFFECTED = @ROWSAFFECTED + @@ROWCOUNT
END
IF @TRACELEVEL = 4
BEGIN
SELECT @MESSAGE = MESSAGE FROM APM.MESSAGES WHERE ID = 50023
RAISERROR (@MESSAGE, 0, 1, @ROWSAFFECTED, @TABLENAME) WITH NOWAIT;
END
END

END TRY

BEGIN CATCH
IF (@@TRANCOUNT &gt; 0)
ROLLBACK TRAN

SELECT
@ERRORNUMBER = ERROR_NUMBER()
,@ERRORSEVERITY = ERROR_SEVERITY()
,@ERRORSTATE = ERROR_STATE()
,@ERRORLINE = ERROR_LINE()
,@ERRORPROCEDURE = ISNULL(ERROR_PROCEDURE(), '-')
,@ERRORMESSAGETEXT = ERROR_MESSAGE()

SET @ERRORIND = 1
END CATCH

IF (@ERRORIND = 1)
BEGIN
DECLARE
@ADJUSTEDERRORSEVERITY INT
,@ERROR_MESSAGE nvarchar(max)

SET @ADJUSTEDERRORSEVERITY = CASE
WHEN @ERRORSEVERITY &gt; 18 THEN 18
ELSE @ERRORSEVERITY
END

SELECT @ERROR_MESSAGE = message FROM APM.Messages WHERE id = 50004
RAISERROR (@ERROR_MESSAGE, @ADJUSTEDERRORSEVERITY, 1
,@ERRORNUMBER
,@ERRORSEVERITY
,@ERRORSTATE
,@ERRORPROCEDURE
,@ERRORLINE
,@ERRORMESSAGETEXT
)
END
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.GetOldComputersOrSources'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.GetOldComputersOrSources AS RETURN 1')
END
GO

alter PROCEDURE APM.GetOldComputersOrSources
@ISCOMPUTER bit, @DEBUG bit
AS
BEGIN
SET NOCOUNT ON

DECLARE
@SQL nvarchar(MAX)
,@FROMITEMTABLE nvarchar(1000)
,@FROMPCITEMTABLE nvarchar(1000)
,@EVENTFIELDS nvarchar(1000)
,@PCFIELDS nvarchar(1000)
,@WHEREITEM nvarchar(1000)
,@WHEREPCITEM nvarchar(1000)

SELECT
@EVENTFIELDS = CASE @ISCOMPUTER WHEN 1
THEN N'm.MACHINEID AS Id, m.MACHINE AS ItemName, t.utceventdate AS LastRefreshDate'
ELSE N's.SOURCEID AS Id, s.SOURCE AS ItemName, t.utceventdate AS LastRefreshDate'
END
,@PCFIELDS = CASE @ISCOMPUTER WHEN 1
THEN N'm.MACHINEID AS Id, m.MACHINE AS ItemName, t.utcdate AS LastRefreshDate'
ELSE N's.SOURCEID AS Id, s.SOURCE AS ItemName, t.utcdate AS LastRefreshDate '
END
,@FROMITEMTABLE = CASE @ISCOMPUTER WHEN 1
THEN N'APM.MACHINE m (NOLOCK)'
ELSE N'APM.SOURCE s (NOLOCK)'
END

,@WHEREITEM = CASE @ISCOMPUTER WHEN 1
THEN N'WHERE t.MACHINEID = m.MACHINEID'
ELSE N'WHERE t.SOURCEID = s.SOURCEID'
END

,@SQL = N'

;WITH AllItemsSet AS
(
SELECT {0}
FROM {2}
OUTER APPLY (
SELECT TOP 1 t.UTCEVENTDATE FROM APM.EVENT t (NOLOCK)
{3}
ORDER BY t.UTCEVENTDATE DESC
) t

UNION ALL

SELECT {1}
FROM {2}
OUTER APPLY (
SELECT TOP 1 t.UTCDATE FROM APM.csEVENT t (NOLOCK)
{3}
ORDER BY t.UTCDATE DESC
) t

UNION ALL

SELECT {1}
FROM {2}
OUTER APPLY (
SELECT TOP 1 t.UTCDATE FROM APM.PerfHourly t (NOLOCK)
{3}
ORDER BY t.UTCDATE DESC
) t
)
SELECT 0 AS Checked, Min(Id) AS Id, ItemName, MAX(LastRefreshDate) AS LastRefreshDate
FROM AllItemsSet
GROUP BY
ItemName
ORDER BY
LastRefreshDate
'
SELECT @SQL = REPLACE(@SQL, N'{0}', @EVENTFIELDS)
SELECT @SQL = REPLACE(@SQL, N'{1}', @PCFIELDS)
SELECT @SQL = REPLACE(@SQL, N'{2}', @FROMITEMTABLE)
SELECT @SQL = REPLACE(@SQL, N'{3}', @WHEREITEM)

IF @DEBUG = 1
PRINT @SQL

EXEC sp_executesql @SQL, N''
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.CalculateOldComputersOrSources'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.CalculateOldComputersOrSources AS RETURN 1')
END
GO

alter PROCEDURE APM.CalculateOldComputersOrSources
@ISCOMPUTER bit, @ITEMS nvarchar(MAX), @DEBUG bit, @RECCOUNT int OUTPUT
AS
BEGIN
SET NOCOUNT ON

IF LEN(@ITEMS) = 0
BEGIN
RAISERROR('Parameter @ITEMS is empty.', 16, 1, 'CalculateOldComputersOrSources')
RETURN
END

DECLARE
@SQL nvarchar(MAX)
,@JOINITEMTABLE nvarchar(1000)
,@JOINFILTER nvarchar(1000)

SELECT
@JOINITEMTABLE = CASE @ISCOMPUTER WHEN 1
THEN N'JOIN APM.MACHINE m (NOLOCK) ON m.MachineId = t.MachineId'
ELSE N'JOIN APM.SOURCE s (NOLOCK) ON s.SourceId = t.SourceId'
END
,@JOINFILTER = CASE @ISCOMPUTER WHEN 1
THEN N'JOIN APM.GetMultiParameters(@ITEMS, @EMPTY) f ON f.VALUE = m.MachineId'
ELSE N'JOIN APM.GetMultiParameters(@ITEMS, @EMPTY) f ON f.VALUE = s.SourceId'
END
,@SQL = N'
;WITH AllItemsSet AS
(
SELECT COUNT(t.eventId) AS recCount
FROM APM.EVENT t(NOLOCK)
{0}
{1}

UNION ALL

SELECT COUNT(t.cseventId) AS recCount
FROM APM.csEVENT t(NOLOCK)
{0}
{1}

UNION ALL

SELECT COUNT(t.perfhourlyId) AS recCount
FROM APM.PERFHOURLY t (NOLOCK)
{0}
{1}
UNION ALL

SELECT COUNT(t.perfdailyId) AS recCount
FROM APM.PERFDAILY t (NOLOCK)
{0}
{1}
)
SELECT @RECCOUNT=SUM(recCount) FROM AllItemsSet
'

DECLARE @PARAMS nvarchar(MAX)

SELECT @SQL = REPLACE(@SQL, N'{0}', @JOINITEMTABLE)
SELECT @SQL = REPLACE(@SQL, N'{1}', @JOINFILTER)

IF @DEBUG = 1
PRINT @SQL

SELECT @PARAMS = N'@ITEMS nvarchar(max), @EMPTY nvarchar(10), @RECCOUNT int OUTPUT'

EXEC sp_executesql @SQL, @PARAMS, @ITEMS, N'', @RECCOUNT = @RECCOUNT OUTPUT
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.GroomingOldComputersOrSources'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.GroomingOldComputersOrSources AS RETURN 1')
END
GO

ALTER PROCEDURE [apm].[GroomingOldComputersOrSources]
@ISCOMPUTER BIT,
@DELETEPERITERATION INT,
@DELETEPERREQUEST int,
@ITEMS nvarchar(MAX),
@DEBUG bit,
@DELETEDCOUNT int OUTPUT,
@DONE bit OUTPUT
AS
BEGIN
SET NOCOUNT ON;

DECLARE
@SERVEREVENTDELETED int
,@CLIENTEVENTDELETED int
,@COUNTERDELETED int


IF @DELETEPERITERATION &lt;= 0
BEGIN
RAISERROR('Parameter @DELETEPERITERATION is less or it is equal to zero.', 16, 1, 'GroomingOldComputersOrSources')
RETURN
END

IF @DELETEPERREQUEST &lt;= 0
BEGIN
RAISERROR('Parameter @DELETEPERREQUEST is less or it is equal to zero.', 16, 1, 'GroomingOldComputersOrSources')
RETURN
END

IF @DELETEPERREQUEST &lt; @DELETEPERITERATION
BEGIN
RAISERROR('Parameter @DELETEPERREQUEST should be greater @DELETEPERITERATION parameter.', 16, 1, 'GroomingOldComputersOrSources')
RETURN
END


IF LEN(@ITEMS) = 0
BEGIN
RAISERROR('Parameter @ITEMS is empty.', 16, 1, 'GroomingOldComputersOrSources')
RETURN
END

DECLARE @ROWSAFFECTED INT

DECLARE
@ERRORIND bit
,@ERRORMESSAGE nvarchar(4000)
,@ERRORNUMBER int
,@ERRORSEVERITY int
,@ERRORSTATE int
,@ERRORLINE int
,@ERRORPROCEDURE sysname
,@ERRORMESSAGETEXT nvarchar(4000)

CREATE TABLE #ItemsToDelete
(
[Value] NVARCHAR(255) collate database_default
)

INSERT INTO #ItemsToDelete
SELECT [Value]
FROM APM.GETMULTIPARAMETERS(@ITEMS, N'')

DECLARE
@SQL nvarchar(MAX)
,@JOINITEMTABLE nvarchar(1000)
,@JOINFILTER nvarchar(1000)

SELECT
@JOINITEMTABLE = CASE @ISCOMPUTER WHEN 1
THEN N'JOIN APM.MACHINE m (NOLOCK) ON m.MachineId = t.MachineId'
ELSE N'JOIN APM.SOURCE s (NOLOCK) ON s.SourceId = t.SourceId'
END
,@JOINFILTER = CASE @ISCOMPUTER WHEN 1
THEN N'JOIN #ItemsToDelete AS f ON f.VALUE = m.MachineId'
ELSE N'JOIN #ItemsToDelete AS f ON f.VALUE = s.SourceId'
END

SET @ERRORIND = 0

BEGIN TRY

DECLARE @DELETEHISTORY TABLE (affected int)

--clear client events events and related referencing tables
SELECT @ROWSAFFECTED = 0

CREATE TABLE #EVENTGROOM (
EVENTID INT
)

CREATE TABLE #TMPPROBINGAPPLICATION (APPLICATIONID int)


SELECT @DELETEDCOUNT = 0

WHILE 1 = 1
BEGIN

SELECT @DONE = 1

-- clear iteration result
DELETE @DELETEHISTORY
TRUNCATE TABLE #EVENTGROOM

SELECT @ROWSAFFECTED = 0

SELECT @SQL = N'
INSERT #EVENTGROOM (EVENTID)
SELECT TOP(@DELETEPERITERATION) t.cseventId
FROM APM.csevent t (nolock)
{0}
{1}
'

SELECT @SQL = REPLACE(@SQL, N'{0}', @JOINITEMTABLE)
SELECT @SQL = REPLACE(@SQL, N'{1}', @JOINFILTER)

IF @DEBUG = 1
PRINT @SQL

DECLARE @PARAMS nvarchar(MAX)

SELECT @PARAMS = N'@DELETEPERITERATION int'

EXEC sp_executesql @SQL, @PARAMS, @DELETEPERITERATION

-- Grooming PageEvent-----
DELETE pe
FROM APM.cspageevent AS pe
JOIN #EVENTGROOM AS eventFilter ON pe.cseventid = eventFilter.EVENTID

-- Grooming Peripheral Details -----
DELETE pd
FROM APM.csperipheraldetail AS pd
JOIN APM.csperipheral AS pe ON pe.csperipheralId = pd.csperipheralId
JOIN #EVENTGROOM AS eventFilter ON pe.cseventid = eventFilter.EVENTID

-- Grooming Peripheral ------
DELETE pe
FROM APM.csperipheral AS pe
JOIN #EVENTGROOM AS eventFilter ON pe.cseventid = eventFilter.EVENTID

-- Grooming csHeaviestResource ---
DELETE hr
FROM APM.csHeaviestResource AS hr
JOIN #EVENTGROOM AS eventFilter ON hr.cseventid = eventFilter.EVENTID

-- Grooming ajax events ---
DELETE aj
FROM APM.csAjax AS aj
JOIN #EVENTGROOM AS eventFilter ON aj.cseventid = eventFilter.EVENTID

-- Grooming async ajax events ---
DELETE aj
FROM APM.csAsyncAjax AS aj
JOIN #EVENTGROOM AS eventFilter ON aj.cseventid = eventFilter.EVENTID

-- Grooming async jscript events ---
DELETE js
FROM APM.csJScriptEvent AS js
JOIN #EVENTGROOM AS eventFilter ON js.cseventid = eventFilter.EVENTID

-- Grooming client exception events ---
DELETE ex
FROM APM.csexevent AS ex
JOIN #EVENTGROOM AS eventFilter ON ex.cseventid = eventFilter.EVENTID

-- Grooming client event detail ---
DELETE ed
FROM APM.CSEVENTDETAIL AS ed
JOIN #EVENTGROOM AS eventFilter ON ed.cseventid = eventFilter.EVENTID

-- Grooming client events ---
DELETE ev
FROM APM.csEvent ev
JOIN #EVENTGROOM AS eventFilter ON ev.cseventid = eventFilter.EVENTID

SELECT @ROWSAFFECTED = @@ROWCOUNT

INSERT @DELETEHISTORY(affected) SELECT @ROWSAFFECTED

--- Save deleted client events --
SELECT @CLIENTEVENTDELETED = @ROWSAFFECTED

TRUNCATE TABLE #EVENTGROOM

--clear server events events and related referencing tables
SELECT @SQL = N'
INSERT #EVENTGROOM (EVENTID)
SELECT TOP(@DELETEPERITERATION) t.eventId
FROM APM.event t (nolock)
{0}
{1}
'

SELECT @SQL = REPLACE(@SQL, N'{0}', @JOINITEMTABLE)
SELECT @SQL = REPLACE(@SQL, N'{1}', @JOINFILTER)

IF @DEBUG = 1
PRINT @SQL

SELECT @PARAMS = N'@DELETEPERITERATION int'

EXEC sp_executesql @SQL, @PARAMS, @DELETEPERITERATION

--- Grooming performance node ---------
DELETE pn
FROM APM.PerformanceNode AS pn
JOIN #EVENTGROOM AS eventFilter ON pn.eventid = eventFilter.EVENTID

DELETE rgn
FROM APM.ResourceGroupNode AS rgn
JOIN #EVENTGROOM AS eventFilter ON rgn.eventid = eventFilter.EVENTID

DELETE en
FROM APM.ExceptionNode AS en
JOIN #EVENTGROOM AS eventFilter ON en.eventid = eventFilter.EVENTID

DELETE ed
FROM APM.EVENTDETAIL AS ed
JOIN #EVENTGROOM AS eventFilter ON ed.eventid = eventFilter.EVENTID

DELETE e
FROM APM.Event AS e
JOIN #EVENTGROOM AS eventFilter ON e.eventid = eventFilter.EVENTID

SELECT @ROWSAFFECTED = @@ROWCOUNT

INSERT @DELETEHISTORY(affected) SELECT @ROWSAFFECTED

-- save deleted server events
SELECT @SERVEREVENTDELETED = @ROWSAFFECTED

--clear PerfHourly table

SELECT @SQL = N'
DELETE TOP(@DELETEPERITERATION) t
FROM APM.PerfHourly t
{0}
{1}
SELECT @ROWSAFFECTED = @@ROWCOUNT
'

SELECT @SQL = REPLACE(@SQL, N'{0}', @JOINITEMTABLE)
SELECT @SQL = REPLACE(@SQL, N'{1}', @JOINFILTER)

IF @DEBUG = 1
PRINT @SQL

SELECT @PARAMS = N'@DELETEPERITERATION int, @ROWSAFFECTED int OUTPUT'

EXEC sp_executesql @SQL, @PARAMS, @DELETEPERITERATION, @ROWSAFFECTED = @ROWSAFFECTED OUTPUT

INSERT @DELETEHISTORY(affected) SELECT @ROWSAFFECTED

-- save deleted counters
SELECT @COUNTERDELETED = @ROWSAFFECTED

--clear PerfDaily table

SELECT @SQL = N'
DELETE TOP(@DELETEPERITERATION) t
FROM APM.PerfDaily t
{0}
{1}
SELECT @ROWSAFFECTED = @@ROWCOUNT
'

SELECT @SQL = REPLACE(@SQL, N'{0}', @JOINITEMTABLE)
SELECT @SQL = REPLACE(@SQL, N'{1}', @JOINFILTER)

IF @DEBUG = 1
PRINT @SQL

SELECT @PARAMS = N'@DELETEPERITERATION int, @ROWSAFFECTED int OUTPUT'

EXEC sp_executesql @SQL, @PARAMS, @DELETEPERITERATION, @ROWSAFFECTED = @ROWSAFFECTED OUTPUT

INSERT @DELETEHISTORY(affected) SELECT @ROWSAFFECTED

--clear APPLICATIONSOURCEMACHINE table
TRUNCATE TABLE #TMPPROBINGAPPLICATION

SELECT @SQL = N'
DELETE TOP(@DELETEPERITERATION) t OUTPUT DELETED.ApplicationId INTO #TMPPROBINGAPPLICATION
FROM APM.APPLICATIONSOURCEMACHINE t
{0}
{1}
SELECT @ROWSAFFECTED = @@ROWCOUNT
'

SELECT @SQL = REPLACE(@SQL, N'{0}', @JOINITEMTABLE)
SELECT @SQL = REPLACE(@SQL, N'{1}', @JOINFILTER)

IF @DEBUG = 1
PRINT @SQL

SELECT @PARAMS = N'@DELETEPERITERATION int, @ROWSAFFECTED int OUTPUT'

EXEC sp_executesql @SQL, @PARAMS, @DELETEPERITERATION, @ROWSAFFECTED = @ROWSAFFECTED OUTPUT

INSERT @DELETEHISTORY(affected) SELECT @ROWSAFFECTED

IF EXISTS(SELECT * FROM @DELETEHISTORY WHERE affected = @DELETEPERITERATION)
SELECT @DONE = 0

SELECT @DELETEDCOUNT = @DELETEDCOUNT + @SERVEREVENTDELETED
+ @CLIENTEVENTDELETED + @COUNTERDELETED

------------------- try delete applications ----------
IF @DONE = 1
BEGIN

--clear Resource table

IF @ISCOMPUTER = 0
WHILE EXISTS
(
SELECT * FROM APM.RESOURCE R
JOIN #ItemsToDelete AS f ON f.VALUE = r.sourceId
)
BEGIN
DELETE TOP(@DELETEPERITERATION) r
FROM APM.Resource R
JOIN #ItemsToDelete AS f ON f.VALUE = r.sourceId
END

DELETE A
FROM APM.APPLICATION A
WHERE
EXISTS
(
SELECT * FROM #TMPPROBINGAPPLICATION tmp
WHERE tmp.APPLICATIONID = A.ApplicationId
) AND
NOT EXISTS
(
SELECT * FROM APM.APPLICATIONSOURCEMACHINE l WITH (NOLOCK)
WHERE l.ApplicationId = A.ApplicationId
)

------------------- try delete machines ----------

IF @ISCOMPUTER = 1
DELETE m
FROM APM.MACHINE m
JOIN #ItemsToDelete AS f ON f.VALUE = m.MachineId

------------------- try delete sources ----------

IF @ISCOMPUTER = 0
DELETE s
FROM APM.Source s
JOIN #ItemsToDelete AS f ON f.VALUE = s.SourceId
BREAK
END

--- Check request result
SELECT @DELETEPERREQUEST = @DELETEPERREQUEST - @SERVEREVENTDELETED
- @CLIENTEVENTDELETED - @COUNTERDELETED

IF @DELETEPERREQUEST &lt;= 0
BREAK
END
END TRY

BEGIN CATCH
IF (@@TRANCOUNT &gt; 0)
ROLLBACK TRAN

SELECT
@ERRORNUMBER = ERROR_NUMBER()
,@ERRORSEVERITY = ERROR_SEVERITY()
,@ERRORSTATE = ERROR_STATE()
,@ERRORLINE = ERROR_LINE()
,@ERRORPROCEDURE = ISNULL(ERROR_PROCEDURE(), '-')
,@ERRORMESSAGETEXT = ERROR_MESSAGE()

SET @ERRORIND = 1
END CATCH

IF (@ERRORIND = 1)
BEGIN
DECLARE
@ADJUSTEDERRORSEVERITY INT
,@ERROR_MESSAGE nvarchar(max)

SET @ADJUSTEDERRORSEVERITY = CASE
WHEN @ERRORSEVERITY &gt; 18 THEN 18
ELSE @ERRORSEVERITY
END

SELECT @ERROR_MESSAGE = message FROM APM.Messages WHERE id = 50004
RAISERROR (@ERROR_MESSAGE, @ADJUSTEDERRORSEVERITY, 1
,@ERRORNUMBER
,@ERRORSEVERITY
,@ERRORSTATE
,@ERRORPROCEDURE
,@ERRORLINE
,@ERRORMESSAGETEXT
)
END
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.GetApplicationGroups'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.GetApplicationGroups AS RETURN 1')
END
GO

/**************************************************************************************************/
/* Procedure return application groups */
/**************************************************************************************************/
alter PROCEDURE APM.GetApplicationGroups
AS
BEGIN
SET NOCOUNT ON

SELECT 0 AS Checked, a.APPLICATIONID AS Id, a.APPLICATION AS ItemName
FROM APM.APPLICATION a (NOLOCK)
WHERE a.APPLICATION != 'All'
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.GroomingOldApplicationGroup'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.GroomingOldApplicationGroup AS RETURN 1')
END
GO


/**************************************************************************************************/
/* Procedure delete unused application groups */
/* Parameters: */
/* @ITEM - Application Group */
/**************************************************************************************************/
alter PROCEDURE APM.GroomingOldApplicationGroup
@ITEM int
AS
BEGIN
SET NOCOUNT ON;

IF EXISTS(SELECT * FROM APM.APPLICATION (NOLOCK)
WHERE APPLICATIONID = @ITEM AND APPLICATION = N'All')
BEGIN
RAISERROR('It is forbidden to delete ''All'' aplication group ', 16, 1, 'GroomingOldApplicationGroup')
RETURN
END

DECLARE @ROWSAFFECTED INT

DECLARE
@ERRORIND bit
,@ERRORMESSAGE nvarchar(4000)
,@ERRORNUMBER int
,@ERRORSEVERITY int
,@ERRORSTATE int
,@ERRORLINE int
,@ERRORPROCEDURE sysname
,@ERRORMESSAGETEXT nvarchar(4000)

SET @ERRORIND = 0

BEGIN TRY

DELETE t
FROM APM.APPLICATIONSOURCEMACHINE t
JOIN APM.APPLICATION a (NOLOCK) ON a.APPLICATIONID = T.APPLICATIONID
WHERE
a.ApplicationId = @ITEM

DELETE APM.APPLICATION WHERE APPLICATIONID = @ITEM

END TRY

BEGIN CATCH
IF (@@TRANCOUNT &gt; 0)
ROLLBACK TRAN

SELECT
@ERRORNUMBER = ERROR_NUMBER()
,@ERRORSEVERITY = ERROR_SEVERITY()
,@ERRORSTATE = ERROR_STATE()
,@ERRORLINE = ERROR_LINE()
,@ERRORPROCEDURE = ISNULL(ERROR_PROCEDURE(), '-')
,@ERRORMESSAGETEXT = ERROR_MESSAGE()

SET @ERRORIND = 1
END CATCH

IF (@ERRORIND = 1)
BEGIN
DECLARE
@ADJUSTEDERRORSEVERITY INT
,@ERROR_MESSAGE nvarchar(max)

SET @ADJUSTEDERRORSEVERITY = CASE
WHEN @ERRORSEVERITY &gt; 18 THEN 18
ELSE @ERRORSEVERITY
END

SELECT @ERROR_MESSAGE = message FROM APM.Messages WHERE id = 50004
RAISERROR (@ERROR_MESSAGE, @ADJUSTEDERRORSEVERITY, 1
,@ERRORNUMBER
,@ERRORSEVERITY
,@ERRORSTATE
,@ERRORPROCEDURE
,@ERRORLINE
,@ERRORMESSAGETEXT
)
END
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.ApplicationStatusClient'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.ApplicationStatusClient AS RETURN 1')
END
GO

/****************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: ApplicationStatusClient */
/* USED IN: Application Status Client Report */
/* INPUT PARAMETERS: */
/* @SOURCEIDS - List of the source id, separated by comma. Exp: '1,2,3' */
/* @COMPUTERIDS - List of the computer id, separated by comma. Exp: '1,2,3' */
/* @ENDDATE - End date of the period (in Client timezone) */
/* @PERIOD - Period type(Day, Week or Month). */
/* - Use for the Start Date calculate of the period */
/* @AVERAGEINTERVAL- This value specifies interval, for which average values will */
/* be calculated. Possible values: 1(1 month), 2(2 month), */
/* 3(3 month), 6(6 month), 17 (7 day) */
/* @TRESHOLD - Event duration treshold */
/* @PROBLEM - Event problem type (all, critical) */
/* @INCLUDESUBNET - List masks, which should be included */
/* @EXCLUDESUBNET - List masks, which should be excluded */
/* @WARNINGTHRESHOLD - Threshold specified by user to notify about warning */
/* @ERRORTHRESHOLD - Threshold specified by user to notify about errors */
/* @TIMEZONE - correlate parameter (timezone by min) to return result */
/* in clien timezone */
/****************************************************************************************/

alter PROCEDURE APM.ApplicationStatusClient
@SOURCEIDS NVARCHAR(MAX),
@COMPUTERIDS NVARCHAR(MAX),
@ENDDATE DATETIME,
@PERIOD INT,
@AVERAGEINTERVAL INT,
@THRESHOLD INT,
@PROBLEM NVARCHAR(10),
@INCLUDESUBNET NVARCHAR(MAX),
@EXCLUDESUBNET NVARCHAR(MAX),
@ERRORTHRESHOLD INT,
@WARNINGTHRESHOLD INT,
@TIMEZONE INT,
@PMSTATUS NVARCHAR(50)
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON;

SELECT
@INCLUDESUBNET = REPLACE(@INCLUDESUBNET, N'*', N'%'),
@EXCLUDESUBNET = REPLACE(@EXCLUDESUBNET, N'*', N'%')

/************************************************************************************/
/* Prepare auxiliary variables for the further calculation */
/************************************************************************************/
DECLARE @CLIENTENDDATE DateTime
SET @CLIENTENDDATE = @ENDDATE

--Convert End date to UTC
SET @ENDDATE = DATEADD(minute, -@TIMEZONE, @CLIENTENDDATE)

--Used for counting average value for last three months
DECLARE @PERIODDAYSCOUNT int
SET @PERIODDAYSCOUNT = (CASE
WHEN @PERIOD = 1 THEN 1
WHEN @PERIOD = 2 THEN 7
WHEN @PERIOD = 3 THEN 31
END)

DECLARE @STARTDATE DateTime
SET @STARTDATE = DATEADD(d, -@PERIODDAYSCOUNT, @ENDDATE)

DECLARE @CLIENTSTARTDATE DateTime
SET @CLIENTSTARTDATE = DATEADD(d, -@PERIODDAYSCOUNT, @CLIENTENDDATE)

DECLARE @HOURSCOUNT int
SET @HOURSCOUNT = (CASE
WHEN @PERIOD = 1 THEN 24
WHEN @PERIOD = 2 THEN 24
WHEN @PERIOD = 3 THEN 1 -- Every day of the month have one hour - 00:00
END)

DECLARE @LASTPERIODSTARTDATE DateTime
SET @LASTPERIODSTARTDATE = DATEADD(d, -@PERIODDAYSCOUNT, @STARTDATE)

DECLARE @AVERAGEPERIODSTARTDATE DateTime
SET @AVERAGEPERIODSTARTDATE = (CASE
WHEN @AVERAGEINTERVAL &lt; 10 THEN DATEADD(month, -@AVERAGEINTERVAL, @STARTDATE)
ELSE DATEADD(day, -(@AVERAGEINTERVAL-10), @STARTDATE)
END)

DECLARE @PROCESSORCOUNTERID INT
SELECT @PROCESSORCOUNTERID = PCtypeId FROM apm.PCType (NOLOCK) WHERE type = N'\Process\% Processor Time'

DECLARE @MEMORYCOUNTERID INT
SELECT @MEMORYCOUNTERID = PCtypeId FROM apm.PCType (NOLOCK) WHERE type = N'\Process\Private Bytes'

DECLARE @IOCOUNTERID INT
SELECT @IOCOUNTERID = PCtypeId FROM apm.PCType (NOLOCK) WHERE type = N'\Process\IO Data Bytes/sec'

DECLARE @MONITOREDREQUESTCOUNTERID INT
SELECT @MONITOREDREQUESTCOUNTERID = PCtypeId FROM apm.PCType (NOLOCK) WHERE type = N'\Apps\Monitored Requests'

DECLARE @REQUESTTIMECOUNTERID INT
SELECT @REQUESTTIMECOUNTERID = PCtypeId FROM apm.PCType (NOLOCK) WHERE type = N'\Apps\Avg. Request Time'
/************************************************************************************/
/* ASSISTING TEMP TABLES */
/************************************************************************************/
-- Filter table, which contains machine ids and source ids
-- typeid defines filter type - 1 for source and 2 for machine
-- valueId filter value - source id and machine id
CREATE TABLE #SOURCEMACHINEFILTERTABLE(
TYPEID INT,
VALUEID INT
)

-- Fill table #SOURCEMACHINEFILTERTABLE
INSERT
INTO #SOURCEMACHINEFILTERTABLE
SELECT
p.typeId AS TYPEID,
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@SOURCEIDS, @COMPUTERIDS) AS p

-- Filter table, which contains PM Statuses of Events
CREATE TABLE #PMSTATUSFILTERTABLE(
VALUEID INT
)

-- Fill table #PMSTATUSFILTERTABLE
INSERT
INTO #PMSTATUSFILTERTABLE
SELECT
CAST(p.VALUE AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@PMSTATUS, N'') AS p

-- Filter table for SubnetC values
CREATE TABLE #SUBNETCFILTERTABLE
(
IPID INT,
SUBNETC NVARCHAR(50) collate database_default
)

-- Insert into filter id of the SubnetC to increase performance for event table
INSERT INTO #SUBNETCFILTERTABLE
SELECT DISTINCT
ipid,
SubNetC
FROM
apm.IP AS ip (NOLOCK)
JOIN APM.GetMultiParameters(CASE WHEN LEN(@INCLUDESUBNET) &gt; 0 THEN @INCLUDESUBNET ELSE N'%' END, N'') AS p1 ON (ip.SubnetC LIKE p1.Value)
LEFT OUTER JOIN APM.GetMultiParameters(CASE WHEN LEN(@EXCLUDESUBNET) &gt; 0 THEN @EXCLUDESUBNET ELSE N'Fake' END, N'') AS p2 ON (ip.SubnetC LIKE p2.Value)
WHERE
--Exclude subnets which have correspondance in @EXCLUDESUBNET parameter
p2.typeId IS NULL

-- To form application pool with all sources run in it, it is need to get all sources and its process
CREATE TABLE #PROCESSFORSOURCE
(
SOURCEID INT,
PCPROCESSID INT,
MACHINEID INT,
EXTRAINFO NVARCHAR(255) collate database_default,
PROCESS NVARCHAR(255) collate database_default
)

INSERT INTO #PROCESSFORSOURCE
SELECT
ph.SourceId,
ph.PCProcessId,
ph.MachineId,
COALESCE(p.Extrainfo, N'') AS EXTRAINFO,
--Select process name till # symbol (w3wp#1 -&gt; w3wp, w3wp -&gt; w3wp)
APM.RemoveProcessIdFromName(p.Process) AS Process
FROM
(
SELECT DISTINCT
ph.SourceId,
ph.pcprocessId,
ph.MachineId
FROM
apm.PerfHourly AS ph (NOLOCK)
WHERE
ph.pcprocessId IS NOT NULL
AND ph.UTCDate &gt;= @STARTDATE
AND ph.UTCDate &lt; @ENDDATE
) AS ph
JOIN apm.PCProcess AS p (NOLOCK) ON p.pcprocessId = ph.pcprocessId
JOIN #SOURCEMACHINEFILTERTABLE AS f ON (f.TYPEID = 2 AND ph.MachineId = f.VALUEID)



/************************************************************************************/
/* Main query */
/************************************************************************************/

-- Report frame. It contains all sources, for which values sould be selected,
-- and dates for the specified period (StartDate : EndDate)
;WITH SourcesDates AS
(
SELECT
s.SourceId,
s.source AS source,
s.RowId,
s.IsClient,
-- Select 1, 7 or 31 day from end date in ClientTime zone, without hours.
-- After that add appropriate hours
DATEADD(HOUR, h.n-1, CONVERT(NVARCHAR, DATEADD(d, -d.n, @CLIENTENDDATE), 112)) AS ClientDate
FROM
(SELECT
ROW_NUMBER() OVER(
PARTITION BY
CASE WHEN s.Source like N'%(Client)' THEN 1
ELSE 0
END
ORDER BY
S.Source
) AS RowId,

s.Source,
S.SourceId,
(CASE WHEN s.Source like N'%(Client)' THEN 1
ELSE 0
END ) AS IsClient
FROM
apm.SOURCE AS s
JOIN #SOURCEMACHINEFILTERTABLE AS sourceFilter ON s.SourceId = sourceFilter.VALUEID
WHERE
sourceFilter.TYPEID = 1
) AS S
CROSS JOIN APM.fn_nums(@PERIODDAYSCOUNT) AS d
CROSS JOIN APM.fn_nums(@HOURSCOUNT) AS h
),

-- Get sources name, ids list separated by comma per app pool
-- This info should be selected for all sources, even they are in the same application pool
-- as in this report grouping by source is applied not by application pool.
AppPoolInfo AS
(
SELECT
c.SOURCEID,
c.EXTRAINFO,
c.PROCESS,
-- all source names which have the same process name as passed in @SOURCEIDS
(SELECT A.source AS [data()]
FROM
(
SELECT DISTINCT
N'''' + s.source + N'''' + N',' AS source
FROM
#PROCESSFORSOURCE AS c1
JOIN Source AS s ON c1.SOURCEID = s.SourceId
WHERE
c1.EXTRAINFO = c.EXTRAINFO
AND c1.PROCESS = c.PROCESS
AND c1.MACHINEID = c.MACHINEID
) AS A
FOR XML PATH ('')
) AS AppPoolSources
FROM
#PROCESSFORSOURCE AS c
JOIN #SOURCEMACHINEFILTERTABLE AS f ON (f.TYPEID = 1 AND f.VALUEID = c.SOURCEID)
GROUP BY
c.SOURCEID,
c.MACHINEID,
c.EXTRAINFO,
c.PROCESS
),
--Add Pool name in-front of source list, if it is executable application, then app pool countains source name
PrepareAppPoolInfo AS (
SELECT DISTINCT
CASE
WHEN COALESCE(info.ExtraInfo,'') = '' THEN CASE info.AppPoolSources WHEN '' THEN '' ELSE LEFT(info.AppPoolSources, LEN(info.AppPoolSources)-1) END
ELSE info.ExtraInfo + CASE info.AppPoolSources WHEN '' THEN '' ELSE ' (' + LEFT(info.AppPoolSources, LEN(info.AppPoolSources) - 1) + ')' END
END AppPool,
info.SourceId,
info.ExtraInfo
FROM
AppPoolInfo AS info
),
-- Forms application pool list for each source
-- Format: AppPool1 ('Source1', 'Source2', Source3), AppPool2 ('Source1', 'Source4')
SourceAppPools AS (
SELECT
s.SourceId,
s.Source,
COALESCE((SELECT a.AppPool AS [data()]
FROM
(
SELECT DISTINCT
info.AppPool + N',' AS AppPool
FROM
PrepareAppPoolInfo as info
WHERE
info.Sourceid = s.Sourceid
) AS A
FOR XML PATH ('')
),s.Source + '-') AS AppPoolInfo
FROM
apm.Source AS s
JOIN #SOURCEMACHINEFILTERTABLE AS f ON (f.TYPEID = 1 AND f.VALUEID = s.SourceId)
),
--Prepares and filters server events for further manipulations
ApplicationStatusClient_EventsFiltered AS
(
SELECT
e.sourceid,
e.eventid,
-- this field is need to determine number of days when
-- there were some events in DB. If number of days is less than 7,
-- then it is supposed that average valu is not correct enought
DATEDIFF(DAY, DATEADD(mi, @TIMEZONE, e.utceventdate), @CLIENTSTARTDATE) AS EventFillFactor,
--Removing APM.GetDatePart replacing the execution by the code below.
--It boosts the overall performance as it reduces the number of calls of scalar function
CASE @PERIOD
WHEN 3 THEN CONVERT(NVARCHAR, DATEADD(mi, @TIMEZONE, e.utceventdate), 112)
ELSE DATEADD(hh,
DATEPART(hh, DATEADD(mi, CAST(@TIMEZONE AS int), e.utceventdate)),
CONVERT(NVARCHAR, DATEADD(mi, @TIMEZONE, e.utceventdate), 112))
END as Date,
--hour is taken as DateDifference in day between 05/04/2009 9:00AM and 05/03/2009 9:00PM is one day,
--despite in case of @PERIOD = 'Day' it can be interpretated as one day (if 05/04/2009 9:00AM is end date), so difference should be taken as 0
(DATEDIFF(hour, e.utceventdate, @ENDDATE)-1) / (@PERIODDAYSCOUNT*24) AS PeriodId
FROM
apm.Event AS e (NOLOCK)
JOIN #SOURCEMACHINEFILTERTABLE AS f1 ON (f1.VALUEID = e.sourceid and f1.TYPEID = 1)
JOIN #SOURCEMACHINEFILTERTABLE AS f2 ON (f2.VALUEID = e.machineid and f2.TYPEID = 2)
JOIN #PMSTATUSFILTERTABLE AS f3 ON (f3.VALUEID = e.PMStatus)
WHERE
((e.EventClassType = N'Performance' AND e.eventduration/1000000.0 &gt;= @THRESHOLD )
OR e.EventClassType = N'exception')
AND (e.category LIKE @PROBLEM OR e.category IS NULL)
AND e.utceventdate &gt;= @AVERAGEPERIODSTARTDATE
AND e.utceventdate &lt; @ENDDATE
),
PrepareEventsServerAvg AS
(
SELECT
e.sourceid AS sourceid,
e.PeriodId,
-- PeriodId is 0 for the current period, 1 for last and 1..n for average
-- This manipulation should shift Client date to current period for
-- other periods - average and last. Client date is in client time zone
DATEADD(day, e.PeriodId*@PERIODDAYSCOUNT, e.Date) AS ClientDate,
MAX(EventFillFactor) AS EventFillFactor,
COUNT(CASE WHEN e.PeriodId = 0 THEN eventid END) AS CurrentEventsCount,
COUNT(CASE WHEN e.PeriodId = 1 THEN eventid END) AS LastEventsCount,
COUNT(CASE WHEN PeriodId &gt; 0 THEN eventid END) AS AvgEventsCount
FROM
ApplicationStatusClient_EventsFiltered AS e
GROUP BY
e.SourceId,
e.PeriodId,
e.Date
),
EventsServer AS
(
SELECT
e.sourceid AS sourceid,
e.ClientDate,
MAX(EventFillFactor) AS EventFillFactor,
MAX(CurrentEventsCount) AS CurrentEventsCount,
MAX(LastEventsCount) AS LastEventsCount,
AVG(CASE WHEN PeriodId &gt; 0 THEN AvgEventsCount*1.0 END) AS AvgEventsCount
FROM
PrepareEventsServerAvg AS e
GROUP BY
sourceid,
e.ClientDate
),

/****************************************************************************************************************/
/* Section selects client events */
/****************************************************************************************************************/
-- Select Client Side events
ApplicationStatusClient_ClientEventsFiltered AS
(
SELECT
e.SourceId,
e.CSEventId AS EventId,
-- this field is need to determine number of days when
-- there were some events in DB. If number of days is less than 7,
-- then it is supposed that average value is not correct enought
DATEDIFF(DAY, DATEADD(mi, @TIMEZONE, e.utcdate), @CLIENTSTARTDATE) AS EventFillFactor,
-- If specified period is Month then take only date part
-- In other cases round date to hours, without minutes and seconds
CASE @PERIOD
WHEN 3 THEN CONVERT(NVARCHAR, DATEADD(mi, @TIMEZONE, e.utcdate), 112)
ELSE DATEADD(hh,
DATEPART(hh, DATEADD(mi, CAST(@TIMEZONE AS int), e.utcdate)),
CONVERT(NVARCHAR, DATEADD(mi, @TIMEZONE, e.utcdate), 112))
END as Date,
--hour is taken as DateDifference in day between 05/04/2009 9:00AM and 05/03/2009 9:00PM is one day,
--despite in case of @PERIOD = 'Day' it can be interpretated as one day (if 05/04/2009 9:00AM is end date), so difference should be taken as 0
(DATEDIFF(hour, e.utcdate, @ENDDATE)- 1) / (@PERIODDAYSCOUNT*24) AS PeriodId
FROM
apm.CSEvent AS e (NOLOCK)
JOIN #SOURCEMACHINEFILTERTABLE AS f1 ON (f1.VALUEID = e.sourceid and f1.TYPEID = 1)
JOIN #SOURCEMACHINEFILTERTABLE AS f2 ON (f2.VALUEID = e.machineid and f2.TYPEID = 2)
JOIN #SUBNETCFILTERTABLE AS f3 ON e.ipid = f3.IPID
JOIN #PMSTATUSFILTERTABLE AS f4 ON (f4.VALUEID = e.PMStatus)
WHERE
e.utcdate &gt;= @AVERAGEPERIODSTARTDATE
AND e.utcdate &lt; @ENDDATE
AND e.PageUri IS NOT NULL
AND (e.ClassType = N'exception' OR e.TotalTime/1000.0 &gt;= @THRESHOLD)
),
-- Group by date (rounded in previous step) and count events
PrepareEventsClientAvg AS
(
SELECT
e.sourceid AS sourceid,
e.PeriodId,
DATEADD(day, e.PeriodId*@PERIODDAYSCOUNT, e.Date) AS ClientDate,
MAX(EventFillFactor) AS EventFillFactor,
COUNT(CASE WHEN e.PeriodId = 0 THEN eventid END) AS CurrentEventsCount,
COUNT(CASE WHEN e.PeriodId = 1 THEN eventid END) AS LastEventsCount,
COUNT(CASE WHEN PeriodId &gt; 0 THEN eventid END) AS AvgEventsCount
FROM
ApplicationStatusClient_ClientEventsFiltered AS e
GROUP BY
e.SourceId,
e.PeriodId,
e.[Date]
),
-- This step is meaningful only for average period AS all events are averaged between "average" period days
EventsClient AS
(
SELECT
e.sourceid AS sourceid,
e.ClientDate,
MAX(EventFillFactor) AS EventFillFactor,
MAX(CurrentEventsCount) AS CurrentEventsCount,
MAX(LastEventsCount) AS LastEventsCount,
AVG(CASE WHEN PeriodId &gt; 0 THEN AvgEventsCount*1.0 END) AS AvgEventsCount
FROM
PrepareEventsClientAvg AS e
GROUP BY
e.SourceId,
e.ClientDate
),
/*************************************************************************************/
/* Activity pcounter queries */
/************************************************************************************/
-- Select Pcounters with specified filtering for activity statistics
ApplicationStatusActivityPerHour AS
(
SELECT
ph.MachineId,
ph.SourceId,
-- this field is need to determine number of days when
-- there were some pc in DB. If number of days is less than 7,
-- then it is supposed that average valu is not correct enought
DATEDIFF(DAY, DATEADD(mi, @TIMEZONE, ph.UTCDate), @CLIENTSTARTDATE) AS ActivityPCFillFactor,
CASE @PERIOD
WHEN 3 THEN CONVERT(NVARCHAR, DATEADD(mi, @TIMEZONE, ph.UTCDate), 112)
ELSE DATEADD(mi, CAST(@TIMEZONE AS int), ph.UTCDate)
END as ClientDate,
(CASE WHEN ph.PCTypeId = @MONITOREDREQUESTCOUNTERID THEN ph.SumValue END) AS MonRequest,
(CASE WHEN ph.PCTypeId = @REQUESTTIMECOUNTERID THEN ph.SumValue / ph.SampleCount END) AS RequestTime,
(DATEDIFF(hour, ph.utcdate, @ENDDATE) - 1) / (@PERIODDAYSCOUNT*24) AS PeriodId
FROM
apm.PerfHourly AS ph (NOLOCK)
JOIN #SOURCEMACHINEFILTERTABLE AS f1 ON (f1.TYPEID = 1 AND ph.SourceId = f1.VALUEID)
JOIN #SOURCEMACHINEFILTERTABLE AS f2 ON (f2.TYPEID = 2 AND f2.VALUEID = ph.MachineId)
WHERE
ph.UTCDate &gt;= @AVERAGEPERIODSTARTDATE
AND ph.UTCDate &lt; @ENDDATE
AND ph.PCTypeID IN (@REQUESTTIMECOUNTERID, @MONITOREDREQUESTCOUNTERID)
),
-- Next step aggregates data only then period is one month.
-- After this step data are aggregated by days.
-- For other periods this step is only pivots data by periods.
ApplicationStatusActivityByDay AS
(
SELECT
MachineId,
SourceId,
PeriodId,
MAX(ActivityPCFillFactor) AS ActivityPCFillFactor,
DATEADD(day, PeriodId*@PERIODDAYSCOUNT, ClientDate) AS ClientDate,
SUM(CASE WHEN PeriodId = 0 THEN MonRequest END) AS CurrentRequestCount,
SUM(CASE WHEN PeriodId = 1 THEN MonRequest END) AS LastRequestCount,
SUM(CASE WHEN PeriodId &gt; 0 THEN MonRequest END) AS AvgRequestCount,
AVG(CASE WHEN PeriodId = 0 THEN RequestTime END) AS CurrentRequestTime,
AVG(CASE WHEN PeriodId = 1 THEN RequestTime END) AS LastRequestTime,
AVG(CASE WHEN PeriodId &gt; 0 THEN RequestTime END) AS AvgRequestTime
FROM
ApplicationStatusActivityPerHour
GROUP BY
MachineId,
SourceId,
PeriodId,
ClientDate
),
-- This step is meaningful only for average period AS all counters are averaged between "average" period dates
ApplicationStatusActivityByPeriod AS
(
SELECT
MachineId,
SourceId,
ClientDate,
MAX(ActivityPCFillFactor) AS ActivityPCFillFactor,
MAX(CurrentRequestCount) AS CurrentRequestCount,
MAX(LastRequestCount) AS LastRequestCount,
AVG(CASE WHEN PeriodId &gt; 0 THEN AvgRequestCount*1.0 END) AS AvgRequestCount,
MAX(CurrentRequestTime) AS CurrentRequestTime,
MAX(LastRequestTime) AS LastRequestTime,
AVG(CASE WHEN PeriodId &gt; 0 THEN AvgRequestTime END) AS AvgRequestTime
FROM
ApplicationStatusActivityByDay
GROUP BY
MachineId,
SourceId,
ClientDate
),
--Aggregate data between machines
ApplicationStatusActivityBySource AS
(
SELECT
SourceId,
ClientDate,
MAX(ActivityPCFillFactor) AS ActivityPCFillFactor,
SUM(CurrentRequestCount) AS CurrentRequestCount,
SUM(LastRequestCount) AS LastRequestCount,
SUM(AvgRequestCount) AS AvgRequestCount,
AVG(CurrentRequestTime) AS CurrentRequestTime,
AVG(LastRequestTime) AS LastRequestTime,
AVG(AvgRequestTime) AS AvgRequestTime
FROM
ApplicationStatusActivityByPeriod
GROUP BY
SourceId,
ClientDate
),
/************************************************************************************/
/* Resources pcounter queries */
/************************************************************************************/
-- Filter resource counters
ApplicationStatusResourcesPerHour AS
(
SELECT
ph.MachineId,
ph.SourceId,
-- this field is need to determine number of days when
-- there were some pc in DB. If number of days is less than 7,
-- then it is supposed that average valu is not correct enought
DATEDIFF(DAY, DATEADD(mi, @TIMEZONE, ph.UTCDate), @CLIENTSTARTDATE) AS ResourcePCFillFactor,
CASE @PERIOD
WHEN 3 THEN CONVERT(NVARCHAR, DATEADD(mi, @TIMEZONE, ph.UTCDate), 112)
ELSE DATEADD(mi, CAST(@TIMEZONE AS int), ph.UTCDate)
END as ClientDate,
(CASE WHEN ph.PCTypeId = @PROCESSORCOUNTERID THEN SUM(ph.SumValue)/SUM(ph.SampleCount) END) AS CPUUsage,
(CASE WHEN ph.PCTypeId = @IOCOUNTERID THEN SUM(ph.SumValue)/SUM(ph.SampleCount) END) AS IOUsage,
(CASE WHEN ph.PCTypeId = @MEMORYCOUNTERID THEN SUM(ph.SumValue)/SUM(ph.SampleCount) END) AS MemoryUsage,
(DATEDIFF(hour, ph.utcdate, @ENDDATE)-1) / (@PERIODDAYSCOUNT*24) AS PeriodId
FROM
apm.PerfHourly AS ph (NOLOCK)
JOIN #SOURCEMACHINEFILTERTABLE AS f1 ON (f1.TYPEID = 1 AND ph.SourceId = f1.VALUEID)
JOIN #SOURCEMACHINEFILTERTABLE AS f2 ON (f2.TYPEID = 2 AND f2.VALUEID = ph.MachineId)
WHERE
ph.UTCDate &gt;= @AVERAGEPERIODSTARTDATE
AND ph.UTCDate &lt; @ENDDATE
AND ph.PCTypeID IN (@PROCESSORCOUNTERID, @IOCOUNTERID, @MEMORYCOUNTERID)
GROUP BY
ph.UTCDate,
ph.PCTypeId,
ph.MachineId,
ph.SourceId
),
-- Group resources by date defined by user. For Period = Week and day this step only devides data by period
ApplicationStatusResourcesByDay AS
(
SELECT
MachineId,
SourceId,
PeriodId,
MAX(ResourcePCFillFactor) AS ResourcePCFillFactor,
DATEADD(day, PeriodId*@PERIODDAYSCOUNT, ClientDate) AS ClientDate,
AVG(CASE WHEN PeriodId = 0 THEN CPUUsage END) AS CurrentCPUUsage,
AVG(CASE WHEN PeriodId = 1 THEN CPUUsage END) AS LastCPUUsage,
AVG(CASE WHEN PeriodId &gt; 0 THEN CPUUsage END) AS AvgCPUUsage,
AVG(CASE WHEN PeriodId = 0 THEN IOUsage END) AS CurrentIOUsage,
AVG(CASE WHEN PeriodId = 1 THEN IOUsage END) AS LastIOUsage,
AVG(CASE WHEN PeriodId &gt; 0 THEN IOUsage END) AS AvgIOUsage,
AVG(CASE WHEN PeriodId = 0 THEN MemoryUsage END) AS CurrentMemoryUsage,
AVG(CASE WHEN PeriodId = 1 THEN MemoryUsage END) AS LastMemoryUsage,
AVG(CASE WHEN PeriodId &gt; 0 THEN MemoryUsage END) AS AvgMemoryUsage
FROM
ApplicationStatusResourcesPerHour
GROUP BY
MachineId,
SourceId,
PeriodId,
ClientDate
),
--This step aggregates data for "average" period, for other periods it is meaningful
ApplicationStatusResourcesByPeriod AS
(
SELECT
SourceId,
ClientDate,
MAX(ResourcePCFillFactor) AS ResourcePCFillFactor,
MAX(CurrentCPUUsage/ COALESCE(m.CPUCount, 1)) AS CurrentCPUUsage,
MAX(LastCPUUsage/ COALESCE(m.CPUCount, 1)) AS LastCPUUsage,
AVG(CASE WHEN PeriodId &gt; 0 THEN AvgCPUUsage/ COALESCE(m.CPUCount, 1) END) AS AvgCPUUsage,
MAX(CurrentIOUsage) AS CurrentIOUsage,
MAX(LastIOUsage) AS LastIOUsage,
AVG(CASE WHEN PeriodId &gt; 0 THEN AvgIOUsage END) AS AvgIOUsage,
MAX(CurrentMemoryUsage) AS CurrentMemoryUsage,
MAX(LastMemoryUsage) AS LastMemoryUsage,
AVG(CASE WHEN PeriodId &gt; 0 THEN AvgMemoryUsage END) AS AvgMemoryUsage
FROM
ApplicationStatusResourcesByDay AS r
JOIN apm.Machine AS m ON m.MachineId = r.MachineId
GROUP BY
r.MachineId,
SourceId,
ClientDate
),
-- Aggregate values between machines
ApplicationStatusResourcesBySource AS
(
SELECT
SourceId,
ClientDate,
MAX(ResourcePCFillFactor) AS ResourcePCFillFactor,
AVG(CurrentCPUUsage) AS CurrentCPUUsage,
AVG(LastCPUUsage) AS LastCPUUsage,
AVG(AvgCPUUsage) AS AvgCPUUsage,
AVG(CurrentIOUsage) AS CurrentIOUsage,
AVG(LastIOUsage) AS LastIOUsage,
AVG(AvgIOUsage) AS AvgIOUsage,
AVG(CurrentMemoryUsage) AS CurrentMemoryUsage,
AVG(LastMemoryUsage) AS LastMemoryUsage,
AVG(AvgMemoryUsage) AS AvgMemoryUsage
FROM
ApplicationStatusResourcesByPeriod
GROUP BY
SourceId,
ClientDate
),
--Check if for some of the machines cpu count is not defined
MachineCPUUndefinedFlag AS
(
SELECT
sf.SOURCEID,
MIN(COALESCE(m.CPUCount, -1)) AS CPUUndefinedFlag
FROM
#PROCESSFORSOURCE AS sf
JOIN apm.Machine AS m (NOLOCK) ON sf.MACHINEID = m.MachineId
GROUP BY
sf.SOURCEID
),
--Combine all data together
CombinedData AS
(
SELECT
SourcesDates.RowId AS RowId,
SourcesDates.IsClient,
SourcesDates.ClientDate,
SourcesDates.Source,
SourcesDates.SourceId,
AppPool.AppPoolInfo,
rpc.CurrentCPUUsage,
rpc.LastCPUUsage,
rpc.AvgCPUUsage,
MAX(rpc.ResourcePCFillFactor) OVER(PARTITION BY SourcesDates.SourceId) AS ResourcePCFillFactor,
(CASE WHEN COALESCE(rpc.AvgCPUUsage, 0) &gt; 0
THEN
ABS(COALESCE(rpc.CurrentCPUUsage,0) - COALESCE(rpc.AvgCPUUsage, 0))*1.0/rpc.AvgCPUUsage
ELSE 0
END) AS CpuStatus,
rpc.CurrentIOUsage/(1024.0) AS CurrentIOUsage,
rpc.LastIOUsage/(1024.0) AS LastIOUsage,
rpc.AvgIOUsage/(1024.0) AS AvgIOUsage,
(CASE WHEN COALESCE(rpc.AvgIOUsage, 0) &gt; 0
THEN
ABS(COALESCE(rpc.CurrentIOUsage,0) - COALESCE(rpc.AvgIOUsage, 0))*1.0/rpc.AvgIOUsage
ELSE 0
END) AS IOStatus,
rpc.CurrentMemoryUsage/(1024.0*1024) AS CurrentMemoryUsage,
rpc.LastMemoryUsage/(1024.0*1024) AS LastMemoryUsage,
rpc.AvgMemoryUsage/(1024.0*1024) AS AvgMemoryUsage,
(CASE WHEN COALESCE(rpc.AvgMemoryUsage, 0) &gt; 0
THEN
ABS(COALESCE(rpc.CurrentMemoryUsage,0) - COALESCE(rpc.AvgMemoryUsage, 0))*1.0/rpc.AvgMemoryUsage
ELSE 0
END) AS MemoryStatus,
MAX(apc.ActivityPCFillFactor) OVER(PARTITION BY SourcesDates.SourceId) AS ActivityPCFillFactor,
apc.CurrentRequestCount,
apc.LastRequestCount,
apc.AvgRequestCount,
(CASE WHEN COALESCE(apc.AvgRequestCount, 0) &gt; 0
THEN
ABS(COALESCE(apc.CurrentRequestCount,0) - COALESCE(apc.AvgRequestCount, 0))*1.0/apc.AvgRequestCount
ELSE 0
END) AS RequestStatus,
apc.CurrentRequestTime/1000.0 AS CurrentRequestTime,
apc.LastRequestTime/1000.0 AS LastRequestTime,
apc.AvgRequestTime/1000.0 AS AvgRequestTime,
(CASE WHEN COALESCE(apc.AvgRequestTime, 0) &gt; 0
THEN
ABS(COALESCE(apc.CurrentRequestTime,0) - COALESCE(apc.AvgRequestTime, 0))*1.0/apc.AvgRequestTime
ELSE 0
END) AS RequestTimeStatus,
MAX(COALESCE(E.EventFillFactor, cs.EventFillFactor)) OVER(PARTITION BY SourcesDates.SourceId) AS EventFillFactor,
COALESCE(E.CurrentEventsCount, cs.CurrentEventsCount) AS CurrentEventsCount,
COALESCE(E.LastEventsCount, cs.LastEventsCount) AS LastEventsCount,
COALESCE(E.AvgEventsCount, cs.AvgEventsCount) AS AvgEventsCount,
(CASE WHEN COALESCE(COALESCE(E.AvgEventsCount, cs.AvgEventsCount), 0) &gt; 0
THEN
ABS(COALESCE(COALESCE(E.CurrentEventsCount, cs.CurrentEventsCount),0) - COALESCE(COALESCE(E.AvgEventsCount, cs.AvgEventsCount), 0))*1.0/COALESCE(E.AvgEventsCount, cs.AvgEventsCount)
ELSE 0
END) AS EventStatus
FROM
SourcesDates
JOIN SourceAppPools AS AppPool ON (AppPool.Sourceid = SourcesDates.Sourceid)
LEFT OUTER JOIN MachineCPUUndefinedFlag AS cpuFlag ON SourcesDates.Sourceid = cpuFlag.Sourceid
LEFT OUTER JOIN ApplicationStatusResourcesBySource AS rpc ON (rpc.ClientDate = SourcesDates.ClientDate AND rpc.SourceId = SourcesDates.Sourceid)
LEFT OUTER JOIN ApplicationStatusActivityBySource AS apc ON (apc.ClientDate = SourcesDates.ClientDate AND apc.SourceId = SourcesDates.Sourceid)
LEFT OUTER JOIN EventsServer AS e ON (e.ClientDate = SourcesDates.ClientDate AND e.SourceId = SourcesDates.Sourceid)
LEFT OUTER JOIN EventsClient AS cs ON (cs.ClientDate = SourcesDates.ClientDate AND cs.SourceId = SourcesDates.Sourceid)

)
SELECT
RowId,
IsClient,
ClientDate,
Source,
SourceId,
AppPoolInfo,
CurrentCPUUsage,
LastCPUUsage,
AvgCPUUsage,
-- If resource counters are presents not more than for 7 day, then don't show threshold message
(CASE WHEN CpuStatus*100 &gt;= @WARNINGTHRESHOLD AND ResourcePCFillFactor &gt;= 7 THEN ClientDate END) AS CPUWarningDate,
(CASE WHEN CpuStatus*100 &gt;= @ERRORTHRESHOLD AND ResourcePCFillFactor &gt;= 7 THEN ClientDate END) AS CPUErrorDate,
CurrentIOUsage,
LastIOUsage,
AvgIOUsage,
-- If resource counters are presents not more than for 7 day, then don't show threshold message
(CASE WHEN IOStatus*100 &gt;= @WARNINGTHRESHOLD AND ResourcePCFillFactor &gt;= 7 THEN ClientDate END) AS IOWarningDate,
(CASE WHEN IOStatus*100 &gt;= @ERRORTHRESHOLD AND ResourcePCFillFactor &gt;= 7 THEN ClientDate END) AS IOErrorDate,
CurrentMemoryUsage,
LastMemoryUsage,
AvgMemoryUsage,
-- If resource counters are presents not more than for 7 day, then don't show threshold message
(CASE WHEN MemoryStatus*100 &gt;= @WARNINGTHRESHOLD AND ResourcePCFillFactor &gt;= 7 THEN ClientDate END) AS MemoryWarningDate,
(CASE WHEN MemoryStatus*100 &gt;= @ERRORTHRESHOLD AND ResourcePCFillFactor &gt;= 7 THEN ClientDate END) AS MemoryErrorDate,
CurrentRequestCount,
LastRequestCount,
AvgRequestCount,
-- If activity counters are presents not more than for 7 day, then don't show threshold message
(CASE WHEN RequestStatus*100 &gt;= @WARNINGTHRESHOLD AND ActivityPCFillFactor &gt;= 7 THEN ClientDate END) AS RequestWarningDate,
(CASE WHEN RequestStatus*100 &gt;= @ERRORTHRESHOLD AND ActivityPCFillFactor &gt;= 7 THEN ClientDate END) AS RequestErrorDate,
CurrentRequestTime,
LastRequestTime,
AvgRequestTime,
-- If activity counters are presents not more than for 7 day, then don't show threshold message
(CASE WHEN RequestTimeStatus*100 &gt;= @WARNINGTHRESHOLD AND ActivityPCFillFactor &gt;= 7 THEN ClientDate END) AS RequestTimeWarningDate,
(CASE WHEN RequestTimeStatus*100 &gt;= @ERRORTHRESHOLD AND ActivityPCFillFactor &gt;= 7 THEN ClientDate END) AS RequestTimeErrorDate,
CurrentEventsCount,
LastEventsCount,
AvgEventsCount,
-- If events are presents not more than for 7 day, then don't show threshold message
(CASE WHEN EventStatus*100 &gt;= @WARNINGTHRESHOLD AND EventFillFactor &gt;= 7 THEN ClientDate END) AS EventWarningDate,
(CASE WHEN EventStatus*100 &gt;= @ERRORTHRESHOLD AND EventFillFactor &gt;= 7 THEN ClientDate END) AS EventErrorDate,
EventStatus,
EventFillFactor,
ActivityPCFillFactor,
ResourcePCFillFactor
FROM
CombinedData
ORDER BY
RowId,
IsClient,
ClientDate
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.ApplicationStatusClientFrequentCSMEvents'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.ApplicationStatusClientFrequentCSMEvents AS RETURN 1')
END
GO

/****************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: ApplicationStatusClientFrequentCSMEvents */
/* USED IN: Application Status Client Report, top 10 Most frequent events */
/* INPUT PARAMETERS: */
/* @SOURCEID - Source id */
/* @COMPUTERIDS - List of the computer id, separated by comma. Exp: '1,2,3' */
/* @ENDDATE - End date of the period (in Client timezone) */
/* @PERIOD - Period type(Day, Week or Month). */
/* - Use for the Start Date calculate of the period */
/* @TRESHOLD - Event duration treshold */
/* @PROBLEM - Event problem type (all, critical) */
/* @INCLUDESUBNET - List masks, which should be included */
/* @EXCLUDESUBNET - List masks, which should be excluded */
/* @TIMEZONE - correlate parameter (timezone by min) to return result */
/* in clien timezone */
/****************************************************************************************/
alter PROCEDURE APM.ApplicationStatusClientFrequentCSMEvents
@SOURCEID INT,
@COMPUTERS NVARCHAR(MAX),
@ENDDATE DATETIME,
@PERIOD INT,
@THRESHOLD DECIMAL(35,0),
@PROBLEM NVARCHAR(10),
@INCLUDESUBNET NVARCHAR(MAX),
@EXCLUDESUBNET NVARCHAR(MAX),
@TIMEZONE INT,
@PMSTATUS NVARCHAR(50)
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON;

SELECT
@INCLUDESUBNET = REPLACE(@INCLUDESUBNET, N'*', N'%'),
@EXCLUDESUBNET = REPLACE(@EXCLUDESUBNET, N'*', N'%')

SET @ENDDATE = DATEADD(minute, -@TIMEZONE, @ENDDATE)

DECLARE @STARTDATE DATETIME
SET @STARTDATE = DATEADD(d, -APM.GetQueryDateCount(@PERIOD, @ENDDATE), @ENDDATE)

DECLARE @LASTPERIODSTARTDATE DateTime
SET @LASTPERIODSTARTDATE = DATEADD(d, -APM.GetQueryDateCount(@PERIOD, @STARTDATE), @STARTDATE)

CREATE TABLE #APPLICATIONSTATUSCLIENT_MACHINE
(
MACHINEID int
)

INSERT
INTO #APPLICATIONSTATUSCLIENT_MACHINE
SELECT
p.value
FROM APM.GetMultiParameters(@COMPUTERS, N'') p

-- Filter table, which contains PM Statuses of Events
CREATE TABLE #PMSTATUSFILTERTABLE(
VALUEID INT
)

-- Fill table #PMSTATUSFILTERTABLE
INSERT
INTO #PMSTATUSFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@PMSTATUS, N'') AS p

-- Filter table for SubnetC values
CREATE TABLE #SUBNETCFILTERTABLE
(
IPID INT,
SUBNETC NVARCHAR(50) collate database_default
)

-- Insert into filter id of the SubnetC to increase performance for event table
INSERT INTO #SUBNETCFILTERTABLE
SELECT DISTINCT
ipid,
SubNetC
FROM
apm.IP AS ip (NOLOCK)
JOIN APM.GetMultiParameters(CASE WHEN LEN(@INCLUDESUBNET) &gt; 0 THEN @INCLUDESUBNET ELSE N'%' END, N'') AS p1 ON (ip.SubnetC LIKE p1.Value)
LEFT OUTER JOIN APM.GetMultiParameters(CASE WHEN LEN(@EXCLUDESUBNET) &gt; 0 THEN @EXCLUDESUBNET ELSE N'Fake' END, N'') AS p2 ON (ip.SubnetC LIKE p2.Value)
WHERE
--Exclude subnets which have correspondance in @EXCLUDESUBNET parameter
p2.typeId IS NULL

;WITH BaseDataSet AS
(
SELECT
eg.[Description],
e.ClassType,
COUNT(CASE WHEN e.utcdate &gt;= @STARTDATE THEN e.cseventid END) as IssuesCount,
COUNT(CASE WHEN e.utcdate &lt; @STARTDATE THEN e.cseventid END) AS LastIssuesCount
FROM
apm.CSEvent (NOLOCK) AS e
JOIN apm.CSEventGroup (NOLOCK) AS eg ON e.csEventGroupId = eg.csEventGroupId
JOIN #APPLICATIONSTATUSCLIENT_MACHINE AS f ON f.MACHINEID = e.MachineId
JOIN #SUBNETCFILTERTABLE AS f1 ON e.ipid = f1.IPID
JOIN #PMSTATUSFILTERTABLE AS f2 ON (f2.VALUEID = e.PMStatus)
WHERE
e.sourceid = @SOURCEID
AND e.utcdate &gt;= @LASTPERIODSTARTDATE
AND e.utcdate &lt; @ENDDATE
AND e.PageUri IS NOT NULL
AND (e.ClassType = N'exception' OR e.TotalTime/1000.0 &gt;= @THRESHOLD)
GROUP BY
eg.Description,
e.ClassType
)

SELECT TOP(10)
ROW_NUMBER() OVER (ORDER BY e.IssuesCount DESC, e.description) AS Id,
e.IssuesCount,
e.LastIssuesCount,
e.Description,
e.ClassType,
COUNT(CASE WHEN e.IssuesCount &gt; 0 THEN 1 ELSE NULL END) OVER() AS TotalCurrentProblemCount,
COUNT(CASE WHEN e.LastIssuesCount &gt; 0 THEN 1 ELSE NULL END) OVER() AS TotalLastProblemCount,
SUM(e.IssuesCount) OVER() AS TotalEventCount,
SUM(e.LastIssuesCount) OVER() AS LastTotalEventCount
FROM
BaseDataSet AS e
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.ApplicationStatusClientFrequentFailure'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.ApplicationStatusClientFrequentFailure AS RETURN 1')
END
GO

/****************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: ApplicationStatusClientFrequentFailure */
/* USED IN: Application Status Client Report, top 10 Most frequent exception events */
/* INPUT PARAMETERS: */
/* @SOURCEID - Source id */
/* @COMPUTERIDS - List of the computer id, separated by comma. Exp: '1,2,3' */
/* @ENDDATE - End date of the period (in Client timezone) */
/* @PERIOD - Period type(Day, Week or Month). */
/* - Use for the Start Date calculate of the period */
/* @PROBLEM - Event problem type (all, critical) */
/* @TIMEZONE - correlate parameter (timezone by min) to return result */
/* in clien timezone */
/****************************************************************************************/
alter PROCEDURE APM.ApplicationStatusClientFrequentFailure
@SOURCEID INT,
@COMPUTERS NVARCHAR(MAX),
@ENDDATE DATETIME,
@PERIOD INT,
@PROBLEM NVARCHAR(10),
@TIMEZONE INT,
@PMSTATUS NVARCHAR(50)
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON;

SET @ENDDATE = DATEADD(minute, -@TIMEZONE, @ENDDATE)

DECLARE @STARTDATE DATETIME
SET @STARTDATE = DATEADD(d, -APM.GetQueryDateCount(@PERIOD, @ENDDATE), @ENDDATE)

CREATE TABLE #APPLICATIONSTATUSCLIENT_MACHINE
(
MACHINEID int
)

INSERT
INTO #APPLICATIONSTATUSCLIENT_MACHINE
SELECT
p.value
FROM APM.GetMultiParameters(@COMPUTERS, N'') p

-- Filter table, which contains PM Statuses of Events
CREATE TABLE #PMSTATUSFILTERTABLE(
VALUEID INT
)

-- Fill table #PMSTATUSFILTERTABLE
INSERT
INTO #PMSTATUSFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@PMSTATUS, N'') AS p

DECLARE @LASTPERIODSTARTDATE DateTime
SET @LASTPERIODSTARTDATE = DATEADD(d, -APM.GetQueryDateCount(@PERIOD, @STARTDATE), @STARTDATE)

DECLARE @CURRENTPERIODENDDATE DateTime
SET @CURRENTPERIODENDDATE = DATEADD(d, APM.GetQueryDateCount(@PERIOD, @STARTDATE), @STARTDATE)


;WITH BaseDataSet AS
(
SELECT
e.description,
e.category,
COUNT(
CASE
WHEN e.utceventdate &gt;= @STARTDATE
THEN e.eventid
END
) as EventsCount,
COUNT(
CASE
WHEN e.utceventdate &lt; @STARTDATE
THEN e.eventid
END
) AS LastEventsCount
FROM
apm.Event (NOLOCK) AS e
JOIN apm.EventGroup AS eg ON e.EventGroupId = eg.EventGroupId
JOIN #APPLICATIONSTATUSCLIENT_MACHINE AS f1 ON e.machineid = f1.MACHINEID
JOIN #PMSTATUSFILTERTABLE AS f3 ON (f3.VALUEID = e.PMStatus)
WHERE
e.EventClassType = N'Exception'
AND (e.category LIKE @PROBLEM)
AND (e.sourceId = @SOURCEID)
AND e.utceventdate &gt;= @LASTPERIODSTARTDATE
AND e.utceventdate &lt; @CURRENTPERIODENDDATE
GROUP BY
e.description, e.category
)
SELECT TOP(10)
ROW_NUMBER() OVER (ORDER BY e.EventsCount DESC, E.description) AS Id,
e.[Description],
e.Category,
e.EventsCount,
e.LastEventsCount,
-- This information is selected for event summary table
SUM(e.EventsCount) OVER() AS TotalEventCount,
SUM(e.LastEventsCount) OVER() AS LastTotalEventCount,
-- Caulculate number of different descriotions (proble, count) in current and last periods
COUNT(CASE WHEN e.EventsCount &gt; 0 THEN 1 ELSE NULL END) OVER() AS CurrentProblemsCount,
COUNT(CASE WHEN e.LastEventsCount &gt; 0 THEN 1 ELSE NULL END) OVER() AS LastProblemsCount
FROM
BaseDataSet AS e
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.ApplicationStatusClientFrequentPerformance'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.ApplicationStatusClientFrequentPerformance AS RETURN 1')
END
GO

/****************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: ApplicationStatusClientFrequentPerformance */
/* USED IN: Application Status Client Report, top 10 Most frequent performance events */
/* INPUT PARAMETERS: */
/* @SOURCEID - Source id */
/* @COMPUTERIDS - List of the computer id, separated by comma. Exp: '1,2,3' */
/* @ENDDATE - End date of the period (in Client timezone) */
/* @PERIOD - Period type(Day, Week or Month). */
/* - Use for the Start Date calculate of the period */
/* @TRESHOLD - Event duration treshold */
/* @PROBLEM - Event problem type (all, critical) */
/* @TIMEZONE - correlate parameter (timezone by min) to return result */
/* in clien timezone */
/****************************************************************************************/

alter PROCEDURE [APM].[ApplicationStatusClientFrequentPerformance]
@SOURCEID INT,
@COMPUTERS NVARCHAR(MAX),
@ENDDATE DATETIME,
@PERIOD INT,
@THRESHOLD DECIMAL(35,0),
@PROBLEM NVARCHAR(10),
@TIMEZONE INT,
@PMSTATUS NVARCHAR(50)
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON;

SET @ENDDATE = DATEADD(minute, -@TIMEZONE, @ENDDATE)

DECLARE @STARTDATE DATETIME
SET @STARTDATE = DATEADD(d, -APM.GetQueryDateCount(@PERIOD, @ENDDATE), @ENDDATE)

CREATE TABLE #APPLICATIONSTATUSCLIENT_MACHINE
(
MACHINEID INT
)

INSERT
INTO #APPLICATIONSTATUSCLIENT_MACHINE
SELECT
p.value
FROM APM.GetMultiParameters(@COMPUTERS, N'') p

-- Filter table, which contains PM Statuses of Events
CREATE TABLE #PMSTATUSFILTERTABLE(
VALUEID INT
)

-- Fill table #PMSTATUSFILTERTABLE
INSERT
INTO #PMSTATUSFILTERTABLE
SELECT
CAST(p.value AS INT) AS VALUEID
FROM
--GetMultiParameters function splits incoming strings. It uses comma as substring delimiter
APM.GetMultiParameters(@PMSTATUS, N'') AS p

DECLARE @LASTPERIODSTARTDATE DateTime
SET @LASTPERIODSTARTDATE = DATEADD(d, -APM.GetQueryDateCount(@PERIOD, @STARTDATE), @STARTDATE)

DECLARE @CURRENTPERIODENDDATE DateTime
SET @CURRENTPERIODENDDATE = DATEADD(d, APM.GetQueryDateCount(@PERIOD, @STARTDATE), @STARTDATE)


;WITH BaseDataSet AS
(
SELECT
COUNT(CASE WHEN e.utceventdate &gt;= @STARTDATE THEN e.eventid END) as IssuesCount,
AVG(CASE WHEN e.utceventdate &gt;= @STARTDATE THEN e.eventduration / 1000000 END) AS AvgDuration,
MAX(CASE WHEN e.utceventdate &gt;= @STARTDATE THEN e.eventduration / 1000000 END) AS MaxDuration,
COUNT(CASE WHEN e.utceventdate &lt; @STARTDATE THEN e.eventid END) AS LastIssuesCount,
e.rootnodename,
(CASE
WHEN pn.description IS NOT NULL THEN RIGHT(pn.description, LEN(pn.description) - CHARINDEX(':', pn.description))
ELSE N''
END) AS PerfNodeDescription
FROM
apm.Event (NOLOCK) AS e
JOIN apm.EventGroup (NOLOCK) AS eg ON e.EventGroupId = eg.EventGroupId
JOIN apm.PerformanceNode (NOLOCK) AS pn ON pn.EventId = e.EventId
JOIN #APPLICATIONSTATUSCLIENT_MACHINE AS f ON f.MACHINEID = e.MachineId
JOIN #PMSTATUSFILTERTABLE AS f1 ON (f1.VALUEID = e.PMStatus)
WHERE
e.EventClassType = N'Performance'
AND e.eventduration / 1000000.0 &gt;= @THRESHOLD
AND e.sourceid = @SOURCEID
AND (e.category LIKE @PROBLEM OR e.category IS NULL)
AND e.utceventdate &gt;= @LASTPERIODSTARTDATE
AND e.utceventdate &lt; @CURRENTPERIODENDDATE
AND (e.HeavyLight &lt;&gt; 0 OR e.HeavyLight IS NULL)
AND pn.ISHeaviestNode = 1
GROUP BY
e.rootnodename,
(CASE
WHEN pn.description IS NOT NULL THEN RIGHT(pn.description, LEN(pn.description) - CHARINDEX(':', pn.description))
ELSE N''
END)
)
SELECT TOP(10)
ROW_NUMBER() OVER (ORDER BY e.IssuesCount DESC, e.rootnodename, PerfNodeDescription) AS Id,
e.IssuesCount,
e.AvgDuration,
e.MaxDuration,
e.LastIssuesCount,
e.rootnodename,
e.PerfNodeDescription,
e.rootnodename + (CASE
WHEN LEN(e.PerfNodeDescription) &gt; 0
THEN ' slow at ' + e.PerfNodeDescription
ELSE N'' END) AS description,
COUNT(CASE WHEN e.IssuesCount &gt; 0 THEN 1 ELSE NULL END) OVER() AS TotalCurrentProblemCount,
COUNT(CASE WHEN e.LastIssuesCount &gt; 0 THEN 1 ELSE NULL END) OVER() AS TotalLastProblemCount,
SUM(e.IssuesCount) OVER() AS TotalEventCount,
SUM(e.LastIssuesCount) OVER() AS TotalLastEventCount
FROM
BaseDataSet AS e
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.ApplicationStatusClientNewCSMEvents'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.ApplicationStatusClientNewCSMEvents AS RETURN 1')
END
GO

/****************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: ApplicationStatusClientNewCSMEvents */
/* USED IN: Application Status Client Report, top 10 New CSM events */
/* INPUT PARAMETERS: */
/* @SOURCEID - Source id */
/* @COMPUTERIDS - List of the computer id, separated by comma. Exp: '1,2,3' */
/* @ENDDATE - End date of the period (in Client timezone) */
/* @PERIOD - Period type(Day, Week or Month). */
/* - Use for the Start Date calculate of the period */
/* @TRESHOLD - Event duration treshold */
/* @PROBLEM - Event problem type (all, critical) */
/* @INCLUDESUBNET - List masks, which should be included */
/* @EXCLUDESUBNET - List masks, which should be excluded */
/* @TIMEZONE - correlate parameter (timezone by min) to return result */
/* in clien timezone */
/****************************************************************************************/

alter PROCEDURE [APM].[ApplicationStatusClientNewCSMEvents]
@SOURCEID INT,
@COMPUTERS NVARCHAR(MAX),
@ENDDATE DATETIME,
@PERIOD INT,
@THRESHOLD DECIMAL(35,0),
@PROBLEM NVARCHAR(10),
@INCLUDESUBNET NVARCHAR(MAX),
@EXCLUDESUBNET NVARCHAR(MAX),
@TIMEZONE INT
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON;

SELECT
@INCLUDESUBNET = REPLACE(@INCLUDESUBNET, N'*', N'%'),
@EXCLUDESUBNET = REPLACE(@EXCLUDESUBNET, N'*', N'%')

SET @ENDDATE = DATEADD(minute, -@TIMEZONE, @ENDDATE)

DECLARE @STARTDATE DATETIME
SET @STARTDATE = DATEADD(d, -APM.GetQueryDateCount(@PERIOD, @ENDDATE), @ENDDATE)

CREATE TABLE #APPLICATIONSTATUSCLIENT_MACHINE
(
MACHINEID INT
)

INSERT
INTO #APPLICATIONSTATUSCLIENT_MACHINE
SELECT
p.value
FROM APM.GetMultiParameters(@COMPUTERS, N'') p

-- Filter table for SubnetC values
CREATE TABLE #SUBNETCFILTERTABLE
(
IPID INT,
SUBNETC NVARCHAR(50) collate database_default
)

-- Insert into filter id of the SubnetC to increase performance for event table
INSERT INTO #SUBNETCFILTERTABLE
SELECT DISTINCT
ipid,
SubNetC
FROM
apm.IP AS ip (NOLOCK)
JOIN APM.GetMultiParameters(CASE WHEN LEN(@INCLUDESUBNET) &gt; 0 THEN @INCLUDESUBNET ELSE N'%' END, N'') AS p1 ON (ip.SubnetC LIKE p1.Value)
LEFT OUTER JOIN APM.GetMultiParameters(CASE WHEN LEN(@EXCLUDESUBNET) &gt; 0 THEN @EXCLUDESUBNET ELSE N'Fake' END, N'') AS p2 ON (ip.SubnetC LIKE p2.Value)
WHERE
--Exclude subnets which have correspondance in @EXCLUDESUBNET parameter
p2.typeId IS NULL

DECLARE @LASTPERIODSTARTDATE DateTime
SET @LASTPERIODSTARTDATE = DATEADD(d, -APM.GetQueryDateCount(@PERIOD, @STARTDATE), @STARTDATE)

DECLARE @CURRENTPERIODENDDATE DateTime
SET @CURRENTPERIODENDDATE = DATEADD(d, APM.GetQueryDateCount(@PERIOD, @STARTDATE), @STARTDATE)


SELECT TOP(10)
ROW_NUMBER() OVER (ORDER BY COUNT(e.CSEventId) DESC, eg.description) AS Id,
COUNT(e.CSEventId) as EventCount,
eg.Description,
e.ClassType,
SUM(COUNT(e.CSEventId)) OVER() AS TotalEventCount,
COUNT(*) OVER() AS TotalNewProblemsCount
FROM
apm.CSEVENT AS e (NOLOCK)
JOIN apm.CSEVENTGROUP AS eg ON e.CSEventGroupId = eg.CSEventGroupId
-- Fileter events by machines
JOIN #APPLICATIONSTATUSCLIENT_MACHINE AS f ON f.MACHINEID = e.machineid
JOIN #SUBNETCFILTERTABLE AS f1 ON e.ipid = f1.IPID
WHERE
((e.ClassType = N'Performance' AND e.TotalTime/1000.0 &gt;= @THRESHOLD)
OR e.ClassType = N'exception')
AND e.utcdate &gt;= @STARTDATE
AND e.utcdate &lt; @ENDDATE
AND e.SourceId = @SOURCEID
AND eg.SourceId = @SOURCEID
AND eg.firsteventdate &gt;= @STARTDATE
AND eg.firsteventdate &lt; @ENDDATE
AND e.PMStatus = 0
AND e.PageUri IS NOT NULL
GROUP BY
eg.Description,
e.ClassType
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.ApplicationStatusClientNewFailure'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.ApplicationStatusClientNewFailure AS RETURN 1')
END
GO


/****************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: ApplicationStatusClientNewFailure */
/* USED IN: Application Status Client Report, top 10 new exception events */
/* INPUT PARAMETERS: */
/* @SOURCEID - Source id */
/* @COMPUTERIDS - List of the computer id, separated by comma. Exp: '1,2,3' */
/* @ENDDATE - End date of the period (in Client timezone) */
/* @PERIOD - Period type(Day, Week or Month). */
/* - Use for the Start Date calculate of the period */
/* @PROBLEM - Event problem type (all, critical) */
/* @TIMEZONE - correlate parameter (timezone by min) to return result */
/* in clien timezone */
/****************************************************************************************/

alter PROCEDURE [APM].[ApplicationStatusClientNewFailure]
@SOURCEID INT,
@COMPUTERS NVARCHAR(MAX),
@ENDDATE DATETIME,
@PERIOD INT,
@PROBLEM NVARCHAR(10),
@TIMEZONE INT
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON;

SET @ENDDATE = DATEADD(minute, -@TIMEZONE, @ENDDATE)

DECLARE @STARTDATE DATETIME
SET @STARTDATE = DATEADD(d, -APM.GetQueryDateCount(@PERIOD, @ENDDATE), @ENDDATE)

CREATE TABLE #APPLICATIONSTATUSCLIENT_MACHINE
(
MACHINEID INT
)

INSERT
INTO #APPLICATIONSTATUSCLIENT_MACHINE
SELECT
p.value
FROM APM.GetMultiParameters(@COMPUTERS, N'') p

SELECT TOP(10)
ROW_NUMBER() OVER (ORDER BY COUNT(e.eventid) DESC, e.description) AS Id,
e.description,
e.category,
COUNT(e.eventid) as EventsCount,
SUM(COUNT(e.eventid)) OVER() AS TotalEventCount,
COUNT(*) OVER() AS TotalNewProblemsCount
FROM
apm.Event (NOLOCK) AS e
JOIN #APPLICATIONSTATUSCLIENT_MACHINE AS f ON f.MACHINEID = e.machineid
JOIN apm.eventgroup (NOLOCK) AS eg ON e.eventGroupId = eg.EventGroupId
WHERE
e.EventClassType = N'Exception'
AND e.SourceId = @SOURCEID
AND eg.SourceId = @SOURCEID
AND (e.category LIKE @PROBLEM)
AND e.utceventdate &gt;= @STARTDATE
AND e.utceventdate &lt; @ENDDATE
AND eg.firsteventdate &gt;= @STARTDATE
AND eg.firsteventdate &lt; @ENDDATE
AND e.PMStatus = 0
GROUP BY
e.description, e.category
END
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.ApplicationStatusClientNewPerformance'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.ApplicationStatusClientNewPerformance AS RETURN 1')
END
GO
/****************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: ApplicationStatusClientNewPerformance */
/* USED IN: Application Status Client Report, top 10 New performance events */
/* INPUT PARAMETERS: */
/* @SOURCEID - Source id */
/* @COMPUTERIDS - List of the computer id, separated by comma. Exp: '1,2,3' */
/* @ENDDATE - End date of the period (in Client timezone) */
/* @PERIOD - Period type(Day, Week or Month). */
/* - Use for the Start Date calculate of the period */
/* @TRESHOLD - Event duration treshold */
/* @PROBLEM - Event problem type (all, critical) */
/* @TIMEZONE - correlate parameter (timezone by min) to return result */
/* in clien timezone */
/****************************************************************************************/
alter PROCEDURE [APM].[ApplicationStatusClientNewPerformance]
@SOURCEID INT,
@COMPUTERS NVARCHAR(MAX),
@ENDDATE DATETIME,
@PERIOD INT,
@THRESHOLD DECIMAL(35,0),
@PROBLEM NVARCHAR(10),
@TIMEZONE INT
WITH RECOMPILE
AS
BEGIN
SET NOCOUNT ON;

SET @ENDDATE = DATEADD(minute, -@TIMEZONE, @ENDDATE)

DECLARE @STARTDATE DATETIME
SET @STARTDATE = DATEADD(d, -APM.GetQueryDateCount(@PERIOD, @ENDDATE), @ENDDATE)

CREATE TABLE #APPLICATIONSTATUSCLIENT_MACHINE
(
MACHINEID INT
)

INSERT
INTO #APPLICATIONSTATUSCLIENT_MACHINE
SELECT
p.value
FROM APM.GetMultiParameters(@COMPUTERS, N'') p
;WITH BaseDatSet AS
(
SELECT
COUNT(e.eventid) as IssuesCount,
AVG(e.eventduration / 1000000) AS AvgDuration,
MAX(e.eventduration / 1000000) AS MaxDuration,
e.rootnodename,
(CASE
WHEN pn.description IS NOT NULL THEN RIGHT(pn.description, LEN(pn.description) - CHARINDEX(':', pn.description))
ELSE N''
END) AS PerfNodeDescription
FROM
APM.Event (nolock) AS e
JOIN #APPLICATIONSTATUSCLIENT_MACHINE AS f ON f.MACHINEID = e.machineid
JOIN APM.PerformanceNode (NOLOCK) AS pn ON pn.EventId = e.EventId
JOIN APM.eventgroup (NOLOCK) AS eg ON E.EventGroupId = eg.EventGroupId
WHERE
e.EventClassType = N'Performance' AND e.eventduration / 1000000.0 &gt;= @THRESHOLD
AND (e.category LIKE @PROBLEM OR e.category IS NULL)
AND e.utceventdate &gt;= @STARTDATE
AND e.utceventdate &lt; @ENDDATE
AND e.SourceId = @SOURCEID
AND eg.SourceId = @SOURCEID
AND eg.firsteventdate &gt;= @STARTDATE
AND eg.firsteventdate &lt; @ENDDATE
AND pn.IsHeaviestNode = 1
AND e.PMStatus = 0
GROUP BY
e.rootnodename,
(CASE
WHEN pn.description IS NOT NULL THEN RIGHT(pn.description, LEN(pn.description) - CHARINDEX(':', pn.description))
ELSE N''
END)
)
SELECT TOP(10)
ROW_NUMBER() OVER (ORDER BY e.IssuesCount DESC, e.rootnodename, e.PerfNodeDescription) AS Id,
e.IssuesCount,
e.AvgDuration,
e.MaxDuration,
e.rootnodename,
e.PerfNodeDescription,
e.rootnodename + (CASE
WHEN LEN(e.PerfNodeDescription) &gt; 0
THEN ' slow at ' + e.PerfNodeDescription
ELSE N'' END) AS description,
SUM(IssuesCount) OVER() AS EventsSum,
COUNT(*) OVER() AS TotalNewProblemsCount
FROM
BaseDatSet AS e
ORDER BY
IssuesCount DESC
END
GO


-------------------- Rule management --------------------------------
IF (OBJECTPROPERTY(OBJECT_ID('APM.V_PM_EMPTY'), 'IsView') IS NULL) BEGIN
EXECUTE('CREATE VIEW APM.V_PM_EMPTY
AS
select clmn=1')
END
GO

alter VIEW [APM].[V_PM_EMPTY] AS
SELECT N'' AS VAL , -1 AS PMSTATUS, -1 AS SEVIEWERDBID, -1 AS EVENTID
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.V_PM_CSEVENTSTATUS'), 'IsView') IS NULL) BEGIN
EXECUTE('CREATE VIEW APM.V_PM_CSEVENTSTATUS
AS
select clmn=1')
END
GO

alter VIEW [APM].[V_PM_CSEVENTSTATUS] AS
SELECT E.CSEVENTID AS EVENTID, E.PMSTATUS, E.ROWGUID, E.SEVIEWERDBID
FROM APM.CSEVENT AS E (NOLOCK)
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.V_PM_HEAVIESTNODE'), 'IsView') IS NULL) BEGIN
EXECUTE('CREATE VIEW APM.V_PM_HEAVIESTNODE
AS
select clmn=1')
END
GO

alter VIEW [APM].[V_PM_HEAVIESTNODE] AS
SELECT
E.EVENTID,
E.PMSTATUS,
E.SEVIEWERDBID,
COALESCE(P.DESCRIPTION, N'Internal Execution') AS VAL,
COALESCE(P.SELFDURATION, E.EVENTDURATION / 1000.0) AS SELFDURATION
FROM
APM.EVENT (NOLOCK) AS e
LEFT JOIN APM.PERFORMANCENODE (NOLOCK) p ON p.eventid = e.eventid
WHERE
p.ISHEAVIESTNODE = 1
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.V_PM_CSHEAVIESTNODE'), 'IsView') IS NULL) BEGIN
EXECUTE('CREATE VIEW APM.V_PM_CSHEAVIESTNODE
AS
select clmn=1')
END
GO

alter VIEW [APM].[V_PM_CSHEAVIESTNODE] AS
SELECT
E.CSEVENTID AS EVENTID,
E.PMSTATUS,
E.SEVIEWERDBID,
COALESCE(P.NAME, N'Internal Execution') AS VAL,
P.DURATION AS SELFDURATION
FROM
APM.CSEVENT (NOLOCK) AS e
LEFT JOIN APM.CSHEAVIESTRESOURCE (NOLOCK) p ON p.cseventid = e.cseventid
WHERE
p.ISHEAVIESTNODE = 1
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.V_PM_EVENT'), 'IsView') IS NULL) BEGIN
EXECUTE('CREATE VIEW APM.V_PM_EVENT
AS
select clmn=1')
END
GO

alter VIEW APM.V_PM_EVENT AS
SELECT
E.EVENTID,
S.SOURCE,
M.MACHINE AS MACHINENAME,
U.NAME AS USERNAME,
E.EVENTCLASSTYPE,
E.ROOTNODENAME,
E.DESCRIPTION,
E.EXCEPTIONCLASS,
E.EVENTDURATION,
E.SEVIEWEREGID,
E.HEAVYLIGHT,
E.ASPECT,
E.SEVIEWERDBID,
E.ROWGUID,
E.CATEGORY,
E.PMSTATUS
FROM APM.EVENT (NOLOCK) AS E
JOIN apm.SOURCE S (NOLOCK) ON S.SOURCEID = E.SOURCEID
JOIN apm.MACHINE M (NOLOCK) ON M.MACHINEID = E.MACHINEID
LEFT JOIN apm.USERS U (NOLOCK) ON U.USERID = E.USERID
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.V_PM_EVENTDETAIL'), 'IsView') IS NULL) BEGIN
EXECUTE('CREATE VIEW APM.V_PM_EVENTDETAIL
AS
select clmn=1')
END
GO

alter VIEW [APM].[V_PM_EVENTDETAIL] AS
SELECT E.EVENTID, E.PMSTATUS, E.SEVIEWERDBID, D.VALUE, D.NAME
FROM APM.EVENT (NOLOCK) AS e
JOIN APM.EVENTDETAIL (NOLOCK) d ON d.eventid = e.eventid
WHERE
d.ValueType = N'PM'
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.V_PM_CSEVENTDETAIL'), 'IsView') IS NULL) BEGIN
EXECUTE('CREATE VIEW APM.V_PM_CSEVENTDETAIL
AS
select clmn=1')
END
GO

alter VIEW [APM].[V_PM_CSEVENTDETAIL] AS
SELECT E.CSEVENTID AS EVENTID, E.PMSTATUS, E.SEVIEWERDBID, D.VALUE, D.NAME
FROM APM.CSEVENT (NOLOCK) AS e
JOIN APM.CSEVENTDETAIL (NOLOCK) d ON d.cseventid = e.cseventid
WHERE
d.ValueType = N'PM'
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.V_PM_RESOURCE'), 'IsView') IS NULL) BEGIN
EXECUTE('CREATE VIEW APM.V_PM_RESOURCE
AS
select clmn=1')
END
GO

alter VIEW [APM].[V_PM_RESOURCE] AS
SELECT P.EVENTID, E.SEVIEWERDBID, E.PMSTATUS, P.RESOURCEMETHOD
FROM APM.PERFORMANCENODE p (NOLOCK)
JOIN apm.EVENT e (NOLOCK) ON e.eventid = p.eventid
WHERE
p.ISHEAVIESTNODE = 1
UNION ALL
SELECT E.EVENTID, E.SEVIEWERDBID, E.PMSTATUS, EX.RESOURCEMETHOD
FROM APM.EXCEPTIONNODE ex (NOLOCK)
JOIN apm.EVENT e (NOLOCK) ON e.eventid = EX.eventid
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.V_PM_CSEVENT'), 'IsView') IS NULL) BEGIN
EXECUTE('CREATE VIEW APM.V_PM_CSEVENT
AS
select clmn=1')
END
GO

alter VIEW APM.V_PM_CSEVENT AS
SELECT
E.CSEVENTID AS EVENTID,
S.SOURCE,
M.MACHINE AS MACHINENAME,
U.NAME AS USERNAME,
E.CLASSTYPE AS EVENTCLASSTYPE,
E.DESCRIPTION AS [DESCRIPTION],
E.TOTALTIME * 1000 AS EVENTDURATION,
SEVIEWEREGID AS EVENTGROUPID,
E.SEVIEWERDBID,
2 AS HEAVYLIGHT,
CASE
WHEN CLASSTYPE = N'exception' THEN N'Web Page Client Side Exception'
END AS EXCEPTIONCLASS,
N'Unknown' AS COMPONENT,
CASE
WHEN CLASSTYPE = N'performance' THEN N'performance'
WHEN CLASSTYPE = N'exception' THEN N'applicationfailure'
END AS ASPECT,
E.ROWGUID,
PMSTATUS,
SEVIEWEREGID
FROM APM.CSEVENT (NOLOCK) AS E
JOIN apm.SOURCE S (NOLOCK) ON S.SOURCEID = E.SOURCEID
JOIN apm.MACHINE M (NOLOCK) ON M.MACHINEID = E.MACHINEID
LEFT JOIN apm.USERS U (NOLOCK) ON U.USERID = E.USERID
GO


IF (OBJECTPROPERTY(OBJECT_ID('APM.PMACTIONQUERY'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.PMACTIONQUERY AS RETURN 1')
END
GO

/******************************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: PMACTIONQUERY */
/* INPUT PARAMETERS: */
/* @RULEDESCRIPTION - rule description */
/* @CLIENT - client event flag : 0 - server event 1 - client event */
/* @DBID - seviewer database id. SEviewerDb primary key */
/* @LASTPARAMETERINDEX - last parameter index */
/* OUTPUT PARAMETERS: */
/* @QUERY_CURSOR - result cursor */
/* DESCRIPTION: */
/* It processed actions and create action parameter description that will be used */
/* during call sp_execute. Also database id parameter has been added into the output */
/* result cursor @QUERY_CURSOR will be contains paramaters description */
/* --------------|------------|-----------------------------------|------------------|-------------| */
/* parameter | field name | action &amp; db paramater descriptions| parameter values | entity name | */
/* --------------|------------|-----------------------------------|------------------|-------------| */
/* For example, rule description has following structure: */
/* &lt;actions&gt; */
/* &lt;action alias="EVENT.PMSTATUS" action="Intercept.ActionType.ChangeStatus"&gt; */
/* &lt;params&gt; */
/* &lt;param name="value" value="3" /&gt; */
/* &lt;/params&gt; */
/* &lt;/action&gt; */
/* &lt;/actions&gt; */
/* Output for this action will be following ( @LASTPARAMETERINDEX = 2, @DBID = 1, @CLIENT = 0 */
/* --------------|------------|-----------------------------------|------------------|-------------| */
/* @A3 | PMSTATUS | @A3 tinyint,@DBID int | 3,1 | EVENT | */
/* --------------|------------|-----------------------------------|------------------|-------------| */
/******************************************************************************************************/
alter PROCEDURE [APM].[PMACTIONQUERY]
@RULEDESCRIPTION as NVARCHAR(max)
,@CLIENT bit
,@DBID int
,@LASTPARAMETERINDEX int = 0
,@QUERY_CURSOR CURSOR VARYING OUTPUT
AS
BEGIN
SET NOCOUNT ON;

DECLARE
@ERRORIND BIT
,@ERRORMESSAGE NVARCHAR(4000)
,@ERRORNUMBER INT
,@ERRORSEVERITY INT
,@ERRORSTATE INT
,@ERRORLINE INT
,@ERRORPROCEDURE SYSNAME
,@ERRORMESSAGETEXT NVARCHAR(4000)

SET @ERRORIND = 0

BEGIN TRY

DECLARE
@RULE AS XML

--convert rule description to untyped xml
SET @RULE = CAST(@RULEDESCRIPTION AS XML)

--declare result query
DECLARE
@QUERYSET TABLE
(
entity SYSNAME -- entity name (stored procedure or table/view)
,actionParameter nvarchar(50) -- action parameter name corresponding action field
,actionField nvarchar(50) -- action field (now "pmstatus")
,params NVARCHAR(MAX) -- list of parameter names (action parameter + database id parameter)
,paramsValues NVARCHAR(MAX) -- parameter values corresponding list of parameter names
,lastParameterIndex int -- last index parameter, for stored procedure is always zero
,procParameterList NVARCHAR(max) -- list of stored proc parameter names
)


--------------- actions query ------------
DECLARE
actions_cursor CURSOR STATIC FOR
SELECT actions._action.query('.')
FROM @RULE.nodes('rule/actions/action') actions(_action)
DECLARE
@ACTION AS XML

OPEN actions_cursor

FETCH NEXT FROM actions_cursor
INTO @ACTION

-------------- cycle by actions --------------
WHILE @@FETCH_STATUS = 0
BEGIN
DECLARE
@ALIAS nvarchar(50)

-- Get alias name that using for extract entity name
SELECT @ALIAS = @ACTION.value('(/action/@alias)[1]', 'nvarchar(50)')

DECLARE
@ENTITY nvarchar(50) -- entity name
,@FIELD nvarchar(50) -- field name
,@FIELDTYPE nvarchar(50) -- field type

DECLARE
@PARAMS NVARCHAR(MAX) -- list of parameter names
,@PARAMSVALUES NVARCHAR(MAX) -- list of parameter values
,@CHARCONDITIONFLAG bit -- char condition flag
,@PROCPARAMETERLIST NVARCHAR(max) --reserved (parameter name list for call stored procedure)
,@ISPROCEDURE bit --entity is procedure. 0 - not procedure 1 - procedure
,@VALUES_CURSOR CURSOR -- cursor for extracting parameter and corresponding values

-- lookup for field, field type, entity name, procedure flag
SELECT
@FIELD = field
,@FIELDTYPE = fieldType
,@ENTITY = entity
,@ISPROCEDURE = isprocedure
FROM
APM.PMENTITYMAPPING (NOLOCK)
WHERE
alias = @ALIAS AND isclient = @CLIENT

IF @@ROWCOUNT = 0
BEGIN
-- alias is not found. raise error
RAISERROR(N'Alias "%s" is not registered', 16, 1, @ALIAS)
RETURN
END

-- clear previos parameter list and check field type.
SELECT
@PARAMS = N''
,@PARAMSVALUES = N''
--flag char character field(1- char field 0- not char field)
,@CHARCONDITIONFLAG = CASE WHEN CHARINDEX(N'char', @FIELDTYPE) &gt; 0 THEN 1 ELSE 0 END

-- initialize parameter list
SELECT
@LASTPARAMETERINDEX = CASE WHEN @ISPROCEDURE = 1 THEN 0 ELSE lastParameterIndex END --last prameter index
,@PARAMS = N''
,@PARAMSVALUES = N''
FROM
@QUERYSET
WHERE
entity = @ENTITY

--------------- values query ------------

--iteration by parameter. Get parameter name and value
SET @VALUES_CURSOR = CURSOR STATIC FOR
SELECT
valueSet.value.value('(@value)[1]', 'nvarchar(max)'), -- parameter value
valueSet.value.value('(@name)[1]', 'nvarchar(max)') -- parameter name
FROM
@ACTION.nodes('/action/params/param') valueSet(value)

-- open cursor
OPEN @VALUES_CURSOR

DECLARE
@VALUE NVARCHAR(MAX) -- parameter value
,@NAME nvarchar(max) -- parameter name
,@DECORATOR nvarchar(1) -- decorator for value

SELECT
@PROCPARAMETERLIST = N'' -- clear proc parameter list
,@DECORATOR = CASE WHEN @CHARCONDITIONFLAG = 1 THEN '''' ELSE '' END -- define value decorator (for example 'value' or value)

-- fetch parameter name and value
FETCH NEXT FROM @VALUES_CURSOR
INTO @VALUE, @NAME

---------- cycle by values --------
WHILE @@FETCH_STATUS = 0
BEGIN
-- increment last parameter index
SELECT @LASTPARAMETERINDEX = @LASTPARAMETERINDEX + 1

DECLARE
@PARAMETERNAME nvarchar(MAX)
,@PARAMETERVALUE nvarchar(max)

SELECT
-- for procedure parameter name equal @NAME otherwise using format "@A{last parameter index}"
@PARAMETERNAME =
CASE
WHEN @ISPROCEDURE = 1
THEN REPLACE(N'@{0}', N'{0}', @NAME)
ELSE REPLACE(N'@A{0}', N'{0}', @LASTPARAMETERINDEX)
END
-- create proc parameter list
IF @ISPROCEDURE = 1
BEGIN
-- parameter list divided by ','
SELECT @PROCPARAMETERLIST = @PROCPARAMETERLIST +
REPLACE(REPLACE(N'{0}{1}',
N'{0}',CASE WHEN LEN(@PROCPARAMETERLIST) &gt; 0 THEN N',' ELSE '' END),
N'{1}',@PARAMETERNAME)
-- calculate parameter type
SELECT @FIELDTYPE = APM.GetProcParameterTypeName(@ENTITY, @PARAMETERNAME)
IF @FIELDTYPE IS NULL
BEGIN
-- parameter type is not divided, raise exception
RAISERROR(N'Parameter "%s" for stored procedure "%s" is not defined.', 16, 1, @PARAMETERNAME, @ENTITY)
RETURN
END
-- define char condition flag
SELECT @CHARCONDITIONFLAG = CASE WHEN CHARINDEX(N'char', @FIELDTYPE) &gt; 0 THEN 1 ELSE 0 END
-- define value decorator (for example 'value' or value)
SELECT @DECORATOR = CASE WHEN @CHARCONDITIONFLAG = 1 THEN '''' ELSE '' END
END
--create parameter value using decorator
SELECT @PARAMETERVALUE = REPLACE(REPLACE(REPLACE(
N'{0}{1}{2}',
N'{0}',@DECORATOR),
N'{1}',@VALUE),
N'{2}',@DECORATOR)
SELECT
-- create parameter list for table/view entity divided by ',' (format - "parameter name parameter type")
@PARAMS = @PARAMS + REPLACE(REPLACE(REPLACE(CONVERT(nvarchar(max),
N'{0}{1} {2}'),
N'{0}',CASE WHEN LEN(@PARAMS) &gt; 0 THEN N',' ELSE N'' END),
N'{1}',@PARAMETERNAME),
N'{2}',@FIELDTYPE)
-- param value list divided by ','
,@PARAMSVALUES = @PARAMSVALUES + REPLACE(REPLACE(CONVERT(nvarchar(max),N'{0}{1}'),
N'{0}',CASE WHEN LEN(@PARAMSVALUES) &gt; 0 THEN N',' ELSE N'' END),
N'{1}',@PARAMETERVALUE)

FETCH NEXT FROM @VALUES_CURSOR
INTO @VALUE, @NAME
END
CLOSE @VALUES_CURSOR
DEALLOCATE @VALUES_CURSOR

--------------- end values query ------------

SELECT
--- Add database id parameter name ----
@PARAMS = @PARAMS + REPLACE(REPLACE(CONVERT(nvarchar(max),N',{0} {1}'),
N'{0}',N'@DBID'),
N'{1}',N'int')

--- Add database id parameter value ----
,@PARAMSVALUES = @PARAMSVALUES + REPLACE(CONVERT(nvarchar(max),N',{0}'),N'{0}',@DBID)

-- insert into result set
INSERT @QUERYSET (actionField, actionParameter, entity, lastParameterIndex, params, paramsValues, procParameterList)
VALUES(@FIELD, @PARAMETERNAME, @ENTITY, @LASTPARAMETERINDEX, @PARAMS, @PARAMSVALUES, @PROCPARAMETERLIST)

--- Get next expression ----------
FETCH NEXT FROM actions_cursor
INTO @ACTION
END
CLOSE actions_cursor
DEALLOCATE actions_cursor

-- create result cursor for action parameter, action field, parameter list, parameter values
SET @QUERY_CURSOR = CURSOR STATIC FORWARD_ONLY FOR
SELECT
actionParameter
,actionField
,params
,paramsValues
,entity
FROM
@QUERYSET

OPEN @QUERY_CURSOR

END TRY
BEGIN CATCH
IF (@@TRANCOUNT &gt; 0)
ROLLBACK TRAN

SELECT
@ERRORNUMBER = ERROR_NUMBER()
,@ERRORSEVERITY = ERROR_SEVERITY()
,@ERRORSTATE = ERROR_STATE()
,@ERRORLINE = ERROR_LINE()
,@ERRORPROCEDURE = ISNULL(ERROR_PROCEDURE(), '-')
,@ERRORMESSAGETEXT = ERROR_MESSAGE()

SET @ERRORIND = 1
END CATCH

IF (@ERRORIND = 1)
BEGIN
IF CURSOR_STATUS('global', 'actions_cursor') IN (0,1)
CLOSE actions_cursor
IF CURSOR_STATUS('global', 'actions_cursor') = -1
DEALLOCATE actions_cursor

DECLARE
@ADJUSTEDERRORSEVERITY INT

SET @ADJUSTEDERRORSEVERITY = CASE
WHEN @ERRORSEVERITY &gt; 18 THEN 18
ELSE @ERRORSEVERITY
END


RAISERROR (@ERRORMESSAGETEXT, @ADJUSTEDERRORSEVERITY, 1
,@ERRORNUMBER
,@ERRORSEVERITY
,@ERRORSTATE
,@ERRORPROCEDURE
,@ERRORLINE
,@ERRORMESSAGETEXT
)
END
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.PMEXPRESSIONQUERY'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.PMEXPRESSIONQUERY AS RETURN 1')
END
GO

/******************************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: PMEXPRESSIONQUERY */
/* INPUT PARAMETERS: */
/* @RULEDESCRIPTION - rule description */
/* @CLIENT - client event flag : 0 - server event 1 - client event */
/* @DBID - seviewer database id. SEviewerDb primary key */
/* OUTPUT PARAMETERS: */
/* @QUERY_CURSOR - result cursor */
/* DESCRIPTION: */
/* It processed expressions and create for each entity "where" sql conditions using list of parameters*/
/* Sql condition also contains action and database id parameters. */
/* If entity is stored procedure then will be create only proc parameter list. */
/* For entity "V_PM_EVENTDETAIL" the column "fieldType" of table PMENTITYMAPPING contains value that */
/* will be used for additional sql condition {Name = {value}}.( See example below for expression */
/* &lt;expression alias="EVENT.COMPONENT"&gt;) */
/* Result cursor will be contains next fields */
/* --------|---------------|------------|------------------|----------------------|----------------- */
/* entity | sql condition | parameters | parameter values | last parameter index | proc parameters */
/* --------|---------------|------------|------------------|----------------------|----------------- */
/* For example, rule description has following structure: */
/*&lt;rule name="Event Type" id="1" dbid="7D7A57B2-32C8-4520-9DA8-1A771BBCC7C8"&gt; */
/* &lt;expressions&gt; */
/* &lt;expression alias="EVENT.EVENTCLASSTYPE" variable="Intercept.Variable.EventClassType"&gt; */
/* &lt;params&gt; */
/* &lt;param name="operation" value="IN" /&gt; */
/* &lt;param name="value" value="performance" /&gt; */
/* &lt;/params&gt; */
/* &lt;/expression&gt; */
/* &lt;expression alias="EVENT.SOURCE" variable="Intercept.Variable.Source"&gt; */
/* &lt;params&gt; */
/* &lt;param name="operation" value="IN" /&gt; */
/* &lt;param name="value" value="Duwamish7" /&gt; */
/* &lt;param name="value" value="Default Web Site/WebService1" /&gt; */
/* &lt;/params&gt; */
/* &lt;/expression&gt; */
/* &lt;expression alias="EVENT.COMPONENT" variable="Intercept.Variable.EventClassType"&gt; */
/* &lt;params&gt; */
/* &lt;param name="operation" value="IN" /&gt; */
/* &lt;param name="value" value="performance" /&gt; */
/* &lt;/params&gt; */
/* &lt;/expression&gt; */
/* &lt;/expressions&gt; */
/* &lt;actions&gt; */
/* &lt;action alias="EVENT.PMSTATUS" action="Intercept.ActionType.ChangeStatus"&gt; */
/* &lt;params&gt; */
/* &lt;param name="value" value="0" /&gt; */
/* &lt;/params&gt; */
/* &lt;/action&gt; */
/* &lt;/actions&gt; */
/*&lt;/rule&gt; */
/* Output for this rule will be following ( @CLIENT = 0, @DBID = 1) */
/* Note: action parameter value and database identifier are not included in parameter value list */
/* -----------|-------------------------|------------------|-------------------------------|-|--| */
/* V_PM_EVENT |(EVENTCLASSTYPE like @P1 | @P1 nvarchar(50) |'performance', |3| | */
/* | |,@P2 nvarchar(255)|'Default Web Site/WebService1',| | | */
/* | ESCAPE N''~'' ) AND |,@P3 nvarchar(255)|'Duwamish7' | | | */
/* | (SOURCE like @P2 | | | | | */
/* | ESCAPE N''~'' OR | | | | | */
/* | SOURCE like @P3 | | | | | */
/* | ESCAPE N''~'') AND | | | | | */
/* | (PMSTATUS != @A1 AND | | | | | */
/* | SEVIEWERDBID = @DBID) | | | | | */
/* | | | | | | */
/* -----------|-------------------------|------------------|-------------------------------|-|--| */
/* V_PM_EVENT |(VALUE like @P4 |@P4 nvarchar(255) |'performance','COMPONENT' |5| | */
/* DETAIL | ESCAPE N''~'' ) AND|@P5 nvarchar(50) | | | | */
/* | NAME=@P5 AND | | | | | */
/* | ( PMSTATUS != @A1 AND | | | | | */
/* | SEVIEWERDBID = @DBID | | | | | */
/* | ) | | | | | */
/* | | | | | | */
/*************|****************************************************************************************/
alter PROCEDURE [APM].[PMEXPRESSIONQUERY]
@RULEDESCRIPTION as NVARCHAR(max)
,@CLIENT bit
,@DBID int
,@QUERY_CURSOR CURSOR VARYING OUTPUT
AS
BEGIN
SET NOCOUNT ON;

DECLARE
@ERRORIND BIT
,@ERRORMESSAGE NVARCHAR(4000)
,@ERRORNUMBER INT
,@ERRORSEVERITY INT
,@ERRORSTATE INT
,@ERRORLINE INT
,@ERRORPROCEDURE SYSNAME
,@ERRORMESSAGETEXT NVARCHAR(4000)

SET @ERRORIND = 0

BEGIN TRY

DECLARE
@RULE AS XML
,@EVENTDETAILENTITY sysname
,@CSEVENTDETAILENTITY sysname

SELECT
-- convert rule to untyped xml
@RULE = CAST(@RULEDESCRIPTION AS XML)
-- server entity name that need processed separate
,@EVENTDETAILENTITY = N'V_PM_EVENTDETAIL'
-- client entity name that need processed separate
,@CSEVENTDETAILENTITY = N'V_PM_CSEVENTDETAIL'

-- Result Set
DECLARE
@QUERYSET TABLE
(
id int IDENTITY (1,1) -- identity . Unique identifier
,entity SYSNAME -- entity name. For eventdetail entity can be several row with the same entity name.
,condition NVARCHAR(MAX) -- sql condition that will be used for 'where' clause
,params NVARCHAR(MAX) -- parameter list that will be used for 'where' clause
,paramsValues NVARCHAR(MAX) --parameter value list that will be used for 'where' clause
,lastParameterIndex int -- last parameter index that used for paramater list
,procParameterList NVARCHAR(max) -- proc parameters if entity is stored proc. Reserved.
)

--------------- expressions query ------------
DECLARE
expressions_cursor CURSOR STATIC FOR
SELECT expressions.expression.query('.') AS expr
FROM @RULE.nodes('rule/expressions/expression') expressions(expression)
DECLARE
@EXPRESSION AS XML

OPEN expressions_cursor

FETCH NEXT FROM expressions_cursor INTO @EXPRESSION

DECLARE
@LASTPARAMETERINDEX int

SELECT @LASTPARAMETERINDEX = 0

-------------- cycle by expressions --------------
WHILE @@FETCH_STATUS = 0
BEGIN
DECLARE
@ALIAS nvarchar(50)

-- Get alias name
SELECT @ALIAS = @EXPRESSION.value('(/expression/@alias)[1]', 'nvarchar(50)')

DECLARE
@ENTITY nvarchar(50) -- entity name
,@FIELD nvarchar(50) -- field name that used in condition
,@OPERATION NVARCHAR(50) -- operation
,@FIELDTYPE nvarchar(50) -- field type
,@NOTEXPRESSION bit -- expression contains 'not' ( 0 - not contains 1 - contains)
,@ISPROCEDURE bit -- entity is procedure ( 0 - table/view 1-procedure)

-- Get operation
SELECT
@OPERATION = @EXPRESSION.value('(/expression/params/param[@name=''operation'']/@value)[1]', 'nvarchar(50)')

SELECT
-- expression contains "not" clause (1-contains, 0-not contains)
@NOTEXPRESSION = CASE WHEN CHARINDEX(N'not', @OPERATION) &gt; 0 THEN 1 ELSE 0 END
-- operation
,@OPERATION = REPLACE(@OPERATION, N'not', N'')

DECLARE
@CONDITION NVARCHAR(MAX) -- sql condition
,@PARAMS NVARCHAR(MAX) -- parameter list divided by ','
,@PARAMSVALUES NVARCHAR(MAX) -- param value list divided by ','
,@PARAMTYPE sysname -- parameter type
,@CHARCONDITIONFLAG bit -- flag char character field(1- char field 0- not char field)
,@PREFIX nvarchar(10) -- for "not" expression use "NOT" clause otherwise use empty prefix
,@PROCPARAMETERLIST NVARCHAR(max) -- proc parameter list
,@VALUES_CURSOR CURSOR -- cursor for extracting parameter and corresponding values

-- seach mapping for alias
SELECT
--use 'rowguid' instead 'eventid' field
@FIELD = CASE field WHEN N'EVENTID' THEN N'ROWGUID' ELSE field END
--user nvarchar(50) for rowguid field
,@FIELDTYPE = CASE field WHEN N'EVENTID' THEN N'nvarchar(50)' ELSE fieldType END
--entity name
,@ENTITY = entity
--stored proc flag
,@ISPROCEDURE = isprocedure
FROM
APM.PMENTITYMAPPING (NOLOCK)
WHERE
alias = @ALIAS AND isclient = @CLIENT

IF @@ROWCOUNT = 0
BEGIN
-- mapping for alias not found, raise exception
RAISERROR(N'Alias "%s" is not registered', 16, 1, @ALIAS)
RETURN
END

-- initialize
SELECT @CONDITION = N''
,@PARAMS = N''
,@PARAMSVALUES = N''
-- use always char condition for eventdetail table or for 'rowguid' field
,@CHARCONDITIONFLAG =
CASE
WHEN (CHARINDEX(N'char', @FIELDTYPE) &gt; 0) OR (@ENTITY = @CSEVENTDETAILENTITY) OR
(@ENTITY = @EVENTDETAILENTITY) OR (@FIELD = N'ROWGUID')
THEN 1
ELSE 0
END
-- initialize prefix. For not char fields use empty prefix
SELECT @PREFIX = CASE WHEN @NOTEXPRESSION = 1 AND @CHARCONDITIONFLAG = 1 THEN N'NOT' ELSE N'' END

-- for not eventdetail entity sql conditions and parameters will be united for the same entity
-- for eventdetail always use new sql condition and parameters
IF (@ENTITY != @CSEVENTDETAILENTITY) AND (@ENTITY != @EVENTDETAILENTITY)
SELECT
@CONDITION = CASE WHEN @ISPROCEDURE = 1 THEN N'' ELSE condition END
,@PARAMS = CASE WHEN @ISPROCEDURE = 1 THEN N'' ELSE params END
,@PARAMSVALUES = CASE WHEN @ISPROCEDURE = 1 THEN N'' ELSE paramsValues END
FROM
@QUERYSET
WHERE
entity = @ENTITY

-- begin create sql condition. The first prefix will be added
SELECT @CONDITION = @CONDITION +
CASE WHEN LEN(@CONDITION) &gt; 0
THEN REPLACE(CONVERT(nvarchar(MAX),N' AND {0} ('), N'{0}', @PREFIX)
ELSE REPLACE(CONVERT(nvarchar(MAX),N' {0} ('), N'{0}', @PREFIX)
END

--------------- values query ------------
-- prepare cursor for select parameter names and values
if @ISPROCEDURE = 1
SET @VALUES_CURSOR = CURSOR STATIC FOR
SELECT valueSet.value.value('(@value)[1]', 'nvarchar(max)'),valueSet.value.value('(@name)[1]', 'nvarchar(max)')
FROM @EXPRESSION.nodes('/expression/params/param') valueSet(value)
ELSE
SET @VALUES_CURSOR = CURSOR STATIC FOR
SELECT valueSet.value.value('(@value)[1]', 'nvarchar(max)'), N''
FROM @EXPRESSION.nodes('/expression/params/param[@name=''value'']') valueSet(value)

-- open values cursor
OPEN @VALUES_CURSOR

DECLARE
@VALUE NVARCHAR(MAX) -- parameter value
,@NAME nvarchar(max) -- parameter name
,@CHARCONDITION nvarchar(max) -- sql condition for char values
,@NUMBERCONDITION nvarchar(max) -- sql condition for non char values
,@DECORATOR nvarchar(1) -- decorator. (Use ''' or empty decorator for values)
,@POSTFIX nvarchar(50) -- postfix

-- calculate operation. use "like" operation instead "IN" for "char" field
SELECT @OPERATION = CASE WHEN LTRIM(@OPERATION) = N'IN' AND @CHARCONDITIONFLAG = 1 THEN N'like' ELSE @OPERATION END

-- initialize sql conditions and parameters
SELECT
@CHARCONDITION = N''
,@NUMBERCONDITION = N''
,@PROCPARAMETERLIST = N''
,@DECORATOR = CASE WHEN @CHARCONDITIONFLAG = 1 THEN '''' ELSE '' END
,@POSTFIX = CASE WHEN CHARINDEX(N'like', @OPERATION) &gt; 0 THEN N' ESCAPE N''''~'''' ' ELSE N'' END

FETCH NEXT FROM @VALUES_CURSOR INTO @VALUE, @NAME

---------- cycle by values --------
WHILE @@FETCH_STATUS = 0
BEGIN
--increment parameter index
SELECT @LASTPARAMETERINDEX = @LASTPARAMETERINDEX + 1

DECLARE
@PARAMETERNAME nvarchar(MAX) -- sql parameter name
,@PARAMETERVALUE nvarchar(max) -- parameter value
,@SQ nvarchar(1) -- char constant

SELECT
@PARAMETERNAME =
CASE
WHEN @ISPROCEDURE = 1
THEN REPLACE(N'@{0}', N'{0}', @NAME)
ELSE REPLACE(N'@P{0}', N'{0}', @LASTPARAMETERINDEX)
END
,@SQ = N''''

IF @ISPROCEDURE = 1
BEGIN
-- procedure. create parameter list
SELECT @PROCPARAMETERLIST = @PROCPARAMETERLIST +
REPLACE(REPLACE(N'{0}{1}',
N'{0}',CASE WHEN LEN(@PROCPARAMETERLIST) &gt; 0 THEN N',' ELSE '' END),
N'{1}',@PARAMETERNAME)
-- get parameter type
SELECT @FIELDTYPE = APM.GetProcParameterTypeName(@ENTITY, @PARAMETERNAME)
IF @FIELDTYPE IS NULL
BEGIN
-- parameter type is not found, raise exception
RAISERROR(N'Parameter "%s" for stored procedure "%s" is not defined.', 16, 1, @PARAMETERNAME, @ENTITY)
RETURN
END
-- setup char condition flag if parameter type is char type
SELECT @CHARCONDITIONFLAG = CASE WHEN CHARINDEX(N'char', @FIELDTYPE) &gt; 0 THEN 1 ELSE 0 END
--decorator value
SELECT @DECORATOR = CASE WHEN @CHARCONDITIONFLAG = 1 THEN '''' ELSE '' END
END

-- calcualte parameter value as decorator + value + decorator
-- use calculate expression 'dbId-value' as value for 'rowguid' field
-- for char parameter value use encoding for char '''
SELECT @PARAMETERVALUE = REPLACE(REPLACE(REPLACE(
N'{0}{1}{2}',
N'{0}',@DECORATOR),
N'{1}',
CASE @FIELD
WHEN N'ROWGUID'
THEN
REPLACE(REPLACE(N'{0}-{1}',
N'{0}', @DBID)
,N'{1}', @VALUE)
ELSE
CASE
WHEN @CHARCONDITIONFLAG = 1
THEN replace(@VALUE, @SQ, @SQ + @SQ)
ELSE @VALUE
END
END
),
N'{2}',@DECORATOR)

-- create char sql condition or non char sql condition ([field] operator [parameter]) ('where' clause)
-- for char condition using 'or' otherwise ','
SELECT
@CHARCONDITION = @CHARCONDITION + REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(CONVERT(nvarchar(MAX),
N' {0} {1} {2} {3} {4}'),
N'{0}',CASE WHEN LEN(@CHARCONDITION) &gt; 0 THEN N' OR ' ELSE N'' END),
N'{1}',@FIELD),
N'{2}',@OPERATION),
N'{3}',@PARAMETERNAME),
N'{4}',@POSTFIX)
,@NUMBERCONDITION = @NUMBERCONDITION + REPLACE(REPLACE(CONVERT(nvarchar(MAX),
N'{0}{1}'),
N'{0}',CASE WHEN LEN(@NUMBERCONDITION) &gt; 0 THEN N',' ELSE '' END),

N'{1}',@PARAMETERNAME)
SELECT
-- create parameter list ([parameter] [parameter type],[parameter] [parameter type],etc)
--use nvarchar(255) for 'eventdetail' entity because field type is not defined for this entity
@PARAMS = @PARAMS + REPLACE(REPLACE(REPLACE(CONVERT(nvarchar(MAX),
N'{0}{1} {2}'),
N'{0}',CASE WHEN LEN(@PARAMS) &gt; 0 THEN N',' ELSE N'' END),
N'{1}',@PARAMETERNAME),
N'{2}',CASE WHEN @ENTITY=@EVENTDETAILENTITY OR @ENTITY=@CSEVENTDETAILENTITY THEN N'nvarchar(255)' ELSE @FIELDTYPE END)

-- create parameter value list ([parameter value], [parameter value],etc)
,@PARAMSVALUES = @PARAMSVALUES + REPLACE(REPLACE(CONVERT(nvarchar(MAX),
N'{0}{1}'),
N'{0}',CASE WHEN LEN(@PARAMSVALUES) &gt; 0
THEN
CASE
WHEN @CHARCONDITIONFLAG = 1
THEN N',N'
ELSE N','
END
ELSE
CASE
WHEN @CHARCONDITIONFLAG = 1
THEN N'N'
ELSE N''
END
END
),
N'{1}',@PARAMETERVALUE)

FETCH NEXT FROM @VALUES_CURSOR INTO @VALUE, @NAME
END
CLOSE @VALUES_CURSOR
DEALLOCATE @VALUES_CURSOR

-- finished create sql condition for non char field
-- ([field] [NOT] @OPERATION [(number condition)])
SELECT @NUMBERCONDITION = REPLACE(REPLACE(REPLACE(REPLACE(CONVERT(nvarchar(MAX),
N'{0} {1} {2} ({3})'),
N'{0}', @FIELD),
N'{1}', CASE WHEN @NOTEXPRESSION = 1 THEN N'NOT' ELSE N'' END),
N'{2}', @OPERATION),
N'{3}', @NUMBERCONDITION)

--user numeric or char sql condition or non char condition. it depends on field type
SELECT @CONDITION = @CONDITION + REPLACE(CONVERT(nvarchar(MAX),N'{0} )'),
N'{0}', CASE WHEN @CHARCONDITIONFLAG = 1 THEN @CHARCONDITION ELSE @NUMBERCONDITION END)
--finished processes current expression
--it is need to joined together the same entity except 'eventdetail' entity and stored proc
--for each row from @QUERYSET will be create separate query. All these query will be intersected.
IF EXISTS(
SELECT * FROM @QUERYSET WHERE entity = @ENTITY AND entity != @EVENTDETAILENTITY
AND entity != @CSEVENTDETAILENTITY
) AND (@ISPROCEDURE = 0)
BEGIN
UPDATE @QUERYSET
SET
condition = @CONDITION -- sql condition
,lastParameterIndex = @LASTPARAMETERINDEX -- last parameter index
,params = @PARAMS -- parameter list
,paramsValues = @PARAMSVALUES -- parameter value list
WHERE
entity = @ENTITY
END
ELSE
BEGIN
-- additional processing for 'eventdetail' entity
--The field 'fieldType' of entity mapping table contains filter value
--for field 'name' of 'eventdetail' entity. Therefore for this entity sql condition will be shown as
-- ['name' = 'fieldType' and 'field' operator 'value']
IF @ENTITY = @EVENTDETAILENTITY OR @ENTITY = @CSEVENTDETAILENTITY
BEGIN
-- increment last parameter index
SELECT @LASTPARAMETERINDEX = @LASTPARAMETERINDEX + 1
--calculate parameter name
SELECT @PARAMETERNAME = REPLACE(N'@P{0}', N'{0}', @LASTPARAMETERINDEX)

--add additional filter by 'name' field
SELECT @CONDITION = @CONDITION +
REPLACE(CONVERT(nvarchar(MAX),N' AND NAME={0}'), N'{0}', @PARAMETERNAME)
--field type is not registered. Use nvarchar(50).
SELECT @PARAMS = @PARAMS +
REPLACE(CONVERT(nvarchar(MAX),N',{0} nvarchar(50)'), N'{0}', @PARAMETERNAME)
-- field type from mapping table contains filter value. It always is char value. Use char decorator.
SELECT @PARAMSVALUES = @PARAMSVALUES +
REPLACE(CONVERT(nvarchar(MAX),N',{0}'), N'{0}',QUOTENAME(@FIELDTYPE, ''''))
END
-- for 'eventdetail' entity always use new query.
INSERT @QUERYSET (entity, condition, lastParameterIndex, params, paramsValues, procParameterList)
VALUES(@ENTITY, @CONDITION, @LASTPARAMETERINDEX, @PARAMS, @PARAMSVALUES, @PROCPARAMETERLIST)
END

--- Get next expression ----
FETCH NEXT FROM expressions_cursor
INTO @EXPRESSION
END
CLOSE expressions_cursor
DEALLOCATE expressions_cursor

-- It is need to add action filter and seviewer database filter to sql condition for each query
---------- added action fields ------

DECLARE
@RESULT_CURSOR CURSOR
,@ID int -- unique identifier for current query. It use because entity can be not unique

-- prepare iteration by each query
SET @RESULT_CURSOR = CURSOR STATIC FOR
SELECT id, entity, condition, params, paramsValues FROM @QUERYSET

OPEN @RESULT_CURSOR

--get current query (unique identifier, entity name, sql condition ('where' clause, parameter list, parameter value list)
FETCH NEXT FROM @RESULT_CURSOR INTO @ID, @ENTITY, @CONDITION, @PARAMS, @PARAMSVALUES

WHILE @@FETCH_STATUS = 0
BEGIN

DECLARE
@ACTIONPARAMS nvarchar(max) --action parameters
,@ACTIONPARAMSVALUES nvarchar(max) --action parameter value
,@ACTIONPARAMETER nvarchar(50) --action parameter name
,@ACTIONFIELD nvarchar(50) -- action field
,@ACTIONENTITY nvarchar(max) -- action entity
,@ACTIONCONDITION nvarchar(MAX) -- action sql condition
,@ACTION_CURSOR CURSOR --It is need for several actions

-- prepare condition for adding action filter
SELECT @ACTIONCONDITION = N'', @CONDITION = @CONDITION + CONVERT(nvarchar(MAX),N' AND (')
--Get action filters. Now there is one action filter
EXEC APM.PMActionQuery @RULEDESCRIPTION, @CLIENT, @DBID, 0, @ACTION_CURSOR OUTPUT

FETCH NEXT FROM @ACTION_CURSOR
INTO @ACTIONPARAMETER, @ACTIONFIELD, @ACTIONPARAMS, @ACTIONPARAMSVALUES,@ACTIONENTITY

WHILE @@FETCH_STATUS = 0
BEGIN
-- create action sql condition ([actionField] != [actionParameter])
--It is need to add filter by seviewer database (SEVIEWERDBID = [seviewer database identifier])
SELECT
@ACTIONCONDITION = @ACTIONCONDITION +
REPLACE(REPLACE(REPLACE(CONVERT(nvarchar(MAX),N' {0} {1} != {2} AND SEVIEWERDBID = @DBID'),
N'{0}', CASE WHEN LEN(@ACTIONCONDITION) &gt; 0 THEN N'OR' ELSE N'' END),
N'{1}', @ACTIONFIELD),
N'{2}', @ACTIONPARAMETER)

--Get next action condition. Now it will be return empty row because use only one action
FETCH NEXT FROM @ACTION_CURSOR
INTO @ACTIONPARAMETER, @ACTIONFIELD, @ACTIONPARAMS, @ACTIONPARAMSVALUES, @ACTIONENTITY
END
CLOSE @ACTION_CURSOR
DEALLOCATE @ACTION_CURSOR

-- join expression sql condition and action sql condition
-- Now action parameter value and database identifier are not included in parameter value list
-- These parameter values (action value and database identifier) will be added to parameter values during execution
-- intersect command
SELECT @CONDITION = @CONDITION + @ACTIONCONDITION + CONVERT(nvarchar(MAX),N')')

--update condition for current query by unique identifier
UPDATE @QUERYSET
SET condition = @CONDITION
WHERE
id = @ID

-- get next query
FETCH NEXT FROM @RESULT_CURSOR INTO @ID, @ENTITY, @CONDITION, @PARAMS, @PARAMSVALUES
END

-- create result cursor
SET @QUERY_CURSOR = CURSOR STATIC FORWARD_ONLY FOR

SELECT
entity -- entity name
,condition -- sql condition
,params -- parameter list
,paramsValues -- parameter value list
,lastParameterIndex -- last parameter index
,procParameterList --proc parameter list
FROM
@QUERYSET

-- open result query
OPEN @QUERY_CURSOR

END TRY
BEGIN CATCH
IF (@@TRANCOUNT &gt; 0)
ROLLBACK TRAN

SELECT
@ERRORNUMBER = ERROR_NUMBER()
,@ERRORSEVERITY = ERROR_SEVERITY()
,@ERRORSTATE = ERROR_STATE()
,@ERRORLINE = ERROR_LINE()
,@ERRORPROCEDURE = ISNULL(ERROR_PROCEDURE(), '-')
,@ERRORMESSAGETEXT = ERROR_MESSAGE()

SET @ERRORIND = 1
END CATCH

IF (@ERRORIND = 1)
BEGIN
IF CURSOR_STATUS('global', 'expressions_cursor') IN (0,1)
CLOSE expressions_cursor
IF CURSOR_STATUS('global', 'expressions_cursor') = -1
DEALLOCATE expressions_cursor

IF CURSOR_STATUS('variable', '@ACTION_CURSOR') IN (0,1)
CLOSE @ACTION_CURSOR
IF CURSOR_STATUS('variable', '@ACTION_CURSOR') = -1
DEALLOCATE @ACTION_CURSOR

IF CURSOR_STATUS('global', 'expressions_cursor') IN (0,1)
CLOSE result_cursor
IF CURSOR_STATUS('global', 'expressions_cursor') = -1
DEALLOCATE result_cursor

DECLARE
@ADJUSTEDERRORSEVERITY INT

SET @ADJUSTEDERRORSEVERITY = CASE
WHEN @ERRORSEVERITY &gt; 18 THEN 18
ELSE @ERRORSEVERITY
END

RAISERROR (@ERRORMESSAGETEXT, @ADJUSTEDERRORSEVERITY, 1
,@ERRORNUMBER
,@ERRORSEVERITY
,@ERRORSTATE
,@ERRORPROCEDURE
,@ERRORLINE
,@ERRORMESSAGETEXT
)
END
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.PMIntersectExpressionQuery'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.PMIntersectExpressionQuery AS RETURN 1')
END
GO

/******************************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: PMIntersectExpressionQuery */
/* INPUT PARAMETERS: */
/* @RULEDESCRIPTION - rule description */
/* @CLIENT - client event flag : 0 - server event 1 - client event */
/* @DBID - seviewer database id. SEviewerDb primary key */
/* OUTPUT PARAMETERS: */
/* @QUERY_CURSOR - result cursor */
/* DESCRIPTION: */
/* It create full sql query for rule. This query intersect all rule expression. Stored procedure are */
/* not supported. It partial implemented. */
/* Result cursor will be contains next fields */
/* --------|---------------|------------|------------------|----------------------|----------------- */
/* entity | sql query | parameters | parameter values | last parameter index | proc parameters */
/* --------|---------------|------------|------------------|----------------------|----------------- */
/* table/ | parameter | parameter | parameter value | | reserved */
/* view/ | query | name | list | | */
/* stored| | parameter | | | */
/* proc | | type | | | */
/* --------|---------------|------------|------------------|----------------------|----------------- */
/******************************************************************************************************/
alter PROCEDURE [APM].[PMIntersectExpressionQuery]
@RULEDESCRIPTION nvarchar(max)
,@CLIENT bit
,@DBID int
,@QUERY_CURSOR CURSOR VARYING OUTPUT
AS
BEGIN
SET NOCOUNT ON;

DECLARE
@ERRORIND BIT
,@ERRORMESSAGE NVARCHAR(4000)
,@ERRORNUMBER INT
,@ERRORSEVERITY INT
,@ERRORSTATE INT
,@ERRORLINE INT
,@ERRORPROCEDURE SYSNAME
,@ERRORMESSAGETEXT NVARCHAR(4000)

SET @ERRORIND = 0

BEGIN TRY

DECLARE
@ENTITY sysname -- entity name
,@CONDITION nvarchar(MAX) -- current sql condition
,@PARAMS nvarchar(MAX) -- parameter list
,@PARAMSVALUES nvarchar(MAX) --parameter value list
,@PROCPARAMETERLIST NVARCHAR(MAX) --reserved
,@LASTPARAMETERINDEX int -- last parameter index
,@QUERY_CUR CURSOR

-- Get queries that will be intercected
EXEC APM.PMExpressionQuery @RULEDESCRIPTION, @CLIENT, @DBID, @QUERY_CUR OUTPUT

--iteration by expression query
FETCH NEXT FROM @QUERY_CUR INTO
@ENTITY, @CONDITION, @PARAMS, @PARAMSVALUES, @LASTPARAMETERINDEX, @PROCPARAMETERLIST

DECLARE
@SQL nvarchar(MAX) -- intersect sql query
,@INTERSECTPARAMS nvarchar(MAX) -- sql parameters for intersect query
,@INTERSECTPARAMSVALUES nvarchar(MAX) -- intersect parameter values


--initialize intersect variables
SELECT @SQL = N'', @INTERSECTPARAMS = N'', @INTERSECTPARAMSVALUES = N''

WHILE @@FETCH_STATUS = 0
BEGIN

IF @CONDITION IS NOT NULL
BEGIN
--create intersect sql query using current expression sql query
SELECT @SQL = @SQL +
REPLACE(REPLACE(REPLACE(CONVERT(nvarchar(max),N'{0} SELECT EVENTID FROM APM.{1} WHERE {2}'),
N'{0}', CASE WHEN LEN(@SQL) &gt; 0 THEN N' INTERSECT' ELSE '' END)
,N'{1}', QUOTENAME(@ENTITY))
,N'{2}', @CONDITION)
--create intercept parameters using current expression sql parameters
SELECT @INTERSECTPARAMS = @INTERSECTPARAMS +
REPLACE(REPLACE(CONVERT(nvarchar(max),N'{0}{1}'),
N'{0}', CASE WHEN LEN(@INTERSECTPARAMS) &gt; 0 THEN N',' ELSE '' END)
,N'{1}', @PARAMS)

--create intersect sql parameter values using current expression parameter values
SELECT @INTERSECTPARAMSVALUES = @INTERSECTPARAMSVALUES +
REPLACE(REPLACE(CONVERT(nvarchar(max),N'{0}{1}'),
N'{0}', CASE WHEN LEN(@INTERSECTPARAMSVALUES) &gt; 0 THEN N',' ELSE '' END)
,N'{1}', @PARAMSVALUES)
END
ELSE
BEGIN
-- stored proc is used if condition is null, now it is not supported, raise exception
RAISERROR (N'The execution of stored procedure is not supported', 16, 1)
RETURN
END

--get next expression query
FETCH NEXT FROM @QUERY_CUR INTO
@ENTITY, @CONDITION, @PARAMS, @PARAMSVALUES, @LASTPARAMETERINDEX, @PROCPARAMETERLIST
END
CLOSE @QUERY_CUR
DEALLOCATE @QUERY_CUR

-- intersect query is created. It is need to add action and database id parameters
DECLARE
@ACTIONPARAMS nvarchar(max) -- action parameters including database id parameter.
,@ACTIONPARAMSVALUES nvarchar(max) -- action parameter values including database id parameter
,@ACTIONPARAMETER nvarchar(50) -- action parameter name. Use only for fetch operation. Don't remove
-- from fetch expression
,@ACTIONFIELD nvarchar(50) -- action field. Use only for fetch operation. Don't remove
-- from fetch expression
,@ACTIONENTITY nvarchar(max) -- action entity. Use only for fetch operation. Don't remove
-- from fetch expression
,@ACTION_CURSOR CURSOR -- action query. It is only one record now.

-- Get action and database id parameters
EXEC APM.PMActionQuery @RULEDESCRIPTION, @CLIENT, @DBID, 0, @ACTION_CURSOR OUTPUT

-- fetch action and database id parameters
FETCH NEXT FROM @ACTION_CURSOR
INTO @ACTIONPARAMETER, @ACTIONFIELD, @ACTIONPARAMS, @ACTIONPARAMSVALUES,@ACTIONENTITY

WHILE @@FETCH_STATUS = 0
BEGIN
SELECT
-- added to intersect parameters
@INTERSECTPARAMS = @INTERSECTPARAMS + REPLACE(CONVERT(nvarchar(max),N',{0}'), N'{0}',@ACTIONPARAMS)
-- added to intersect parameter values
,@INTERSECTPARAMSVALUES = @INTERSECTPARAMSVALUES + REPLACE(CONVERT(nvarchar(max),N',{0}'), N'{0}',@ACTIONPARAMSVALUES)

-- fetch next action and database id parameters.
FETCH NEXT FROM @ACTION_CURSOR
INTO @ACTIONPARAMETER, @ACTIONFIELD, @ACTIONPARAMS, @ACTIONPARAMSVALUES, @ACTIONENTITY
END
CLOSE @ACTION_CURSOR
DEALLOCATE @ACTION_CURSOR

--create result sql query
DECLARE
@QUERYSET TABLE
(
entity SYSNAME --view/table or stored proc. reserved
,condition NVARCHAR(MAX) --sql query
,params NVARCHAR(MAX) -- sql parameter list
,paramsValues NVARCHAR(MAX) -- sql parameter values
,lastParameterIndex int -- reserved
,procParameterList NVARCHAR(max) -- reserved
)

INSERT @QUERYSET
(
entity,
condition,
params,
paramsValues,
lastParameterIndex,
procParameterList
)
SELECT
@ENTITY --view/table or stored proc. reserved
,@SQL --sql query
,@INTERSECTPARAMS -- sql parameter list
,@INTERSECTPARAMSVALUES -- sql parameter values
,@LASTPARAMETERINDEX -- reserved
,@PROCPARAMETERLIST -- reserved

--create result cursor
SET @QUERY_CURSOR = CURSOR STATIC FOR SELECT * FROM @QUERYSET
--open cursor
OPEN @QUERY_CURSOR

END TRY
BEGIN CATCH
IF (@@TRANCOUNT &gt; 0)
ROLLBACK TRAN

SELECT
@ERRORNUMBER = ERROR_NUMBER()
,@ERRORSEVERITY = ERROR_SEVERITY()
,@ERRORSTATE = ERROR_STATE()
,@ERRORLINE = ERROR_LINE()
,@ERRORPROCEDURE = ISNULL(ERROR_PROCEDURE(), '-')
,@ERRORMESSAGETEXT = ERROR_MESSAGE()

SET @ERRORIND = 1
END CATCH

IF (@ERRORIND = 1)
BEGIN
IF CURSOR_STATUS('variable', '@QUERY_CUR') IN (0,1)
CLOSE @QUERY_CUR
IF CURSOR_STATUS('variable', '@QUERY_CUR') = -1
DEALLOCATE @QUERY_CUR

DECLARE
@ADJUSTEDERRORSEVERITY INT

SET @ADJUSTEDERRORSEVERITY = CASE
WHEN @ERRORSEVERITY &gt; 18 THEN 18
ELSE @ERRORSEVERITY
END


RAISERROR (@ERRORMESSAGETEXT, @ADJUSTEDERRORSEVERITY, 1
,@ERRORNUMBER
,@ERRORSEVERITY
,@ERRORSTATE
,@ERRORPROCEDURE
,@ERRORLINE
,@ERRORMESSAGETEXT
)
END
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.PMQueryForRule'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.PMQueryForRule AS RETURN 1')
END
GO

/******************************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: PMQueryForRule */
/* INPUT PARAMETERS: */
/* @RULEDESCRIPTION - rule description */
/* @CLIENT - client event flag : 0 - server event 1 - client event */
/* @DBID - seviewer database id. SEviewerDb primary key */
/* @CALCULATETOTAL - calculate total flag (1- it is need to calculate count of records */
/* 0- it is need to fetch records) */
/* @ROWSPERITERATION - number of records that is need to fetch */
/* @DEBUG - 0-trace information will be not print */
/* 1-trace information will be print */
/* DESCRIPTION: */
/* Calculate total records or fetch records that will be apply by rule. */
/* It is need external temporary tables #QUERYTEXT and #RESULTTABLE for execute. */
/* #QUERYTEXT table is used for cache sql query (decrease execution count of xml operations). */
/* Total count or records will be inserted into the #RESULT table */
/******************************************************************************************************/
alter PROCEDURE [APM].[PMQueryForRule]
@RULEDESCRIPTION nvarchar(max)
,@CLIENT bit
,@DBID int
,@CALCULATETOTAL bit
,@ROWSPERITERATION int
,@DEBUG bit = 0
AS
BEGIN
SET NOCOUNT ON;

DECLARE
@ERRORIND BIT
,@ERRORMESSAGE NVARCHAR(4000)
,@ERRORNUMBER INT
,@ERRORSEVERITY INT
,@ERRORSTATE INT
,@ERRORLINE INT
,@ERRORPROCEDURE SYSNAME
,@ERRORMESSAGETEXT NVARCHAR(4000)

SET @ERRORIND = 0

BEGIN TRY

DECLARE
@ENTITY sysname -- entity name or stored proc name
,@CONDITION nvarchar(MAX) -- sql query for execution
,@PARAMS nvarchar(MAX) -- sql query parameter list
,@PARAMSVALUES nvarchar(MAX) -- sql query parameter values
,@PROCPARAMETERLIST NVARCHAR(MAX) -- reserved
,@LASTPARAMETERINDEX int -- reserved
,@QUERY_CUR CURSOR -- query cursor

DECLARE
@SQL nvarchar(MAX)

-- cache is empty ?
IF NOT EXISTS(SELECT * FROM #QUERYTEXT WHERE UPDATESQL = 0)
BEGIN
---create intersect query that will be execute
EXEC APM.PMIntersectExpressionQuery @RULEDESCRIPTION, @CLIENT, @DBID, @QUERY_CUR OUTPUT

-- get intersect query
FETCH NEXT FROM @QUERY_CUR INTO
@ENTITY, @CONDITION, @PARAMS, @PARAMSVALUES, @LASTPARAMETERINDEX, @PROCPARAMETERLIST

WHILE @@FETCH_STATUS = 0
BEGIN
DECLARE
@COMMAND nvarchar(MAX)

--stored proc ?
IF @CONDITION IS NOT NULL
-- create sql for extract (calculate total) event id corresponding rule
SELECT @COMMAND =
REPLACE(REPLACE(CONVERT(nvarchar(max),N'SELECT {0} FROM ({1}) AS A'),
N'{0}', CASE
WHEN @CALCULATETOTAL = 0 THEN REPLACE(N'TOP({0}) A.EVENTID', N'{0}', @ROWSPERITERATION)
ELSE N'COUNT(*)'
END)
,N'{1}', @CONDITION)
ELSE -- stored proc
SELECT @COMMAND =
REPLACE(REPLACE(N'EXEC APM.{0} {1}',
N'{0}', @ENTITY),
N'{1}', @PROCPARAMETERLIST)
-- create sql for call sp_execute that will execute intersect query
SELECT @SQL = REPLACE(REPLACE(REPLACE(CONVERT(nvarchar(max),N'sp_executesql N''{0}'', N''{1}'', {2}'),
N'{0}',@COMMAND),
N'{1}',@PARAMS),
N'{2}',@PARAMSVALUES)
-- save result query to cache
INSERT #QUERYTEXT(SQLTEXT, UPDATESQL) SELECT @SQL, 0

IF @DEBUG = 1
BEGIN
PRINT @SQL
END

--fetch next intersect query
FETCH NEXT FROM @QUERY_CUR INTO
@ENTITY, @CONDITION, @PARAMS, @PARAMSVALUES, @LASTPARAMETERINDEX, @PROCPARAMETERLIST;
-- There is additional query only if it contains stored proc. Now stored proc is not supported
IF @@FETCH_STATUS = 0
BEGIN
-- query contains stored proc, raise exception
RAISERROR (N'The execution of stored procedure is not supported', 16, 1)
RETURN
END

END
CLOSE @QUERY_CUR
DEALLOCATE @QUERY_CUR

END

--get result query from cache
SELECT TOP (1) @SQL = SQLTEXT FROM #QUERYTEXT WHERE UPDATESQL = 0

--save result of query execution to external temporary table
INSERT #RESULTTABLE EXEC sp_executesql @SQL

END TRY
BEGIN CATCH
IF (@@TRANCOUNT &gt; 0)
ROLLBACK TRAN

SELECT
@ERRORNUMBER = ERROR_NUMBER()
,@ERRORSEVERITY = ERROR_SEVERITY()
,@ERRORSTATE = ERROR_STATE()
,@ERRORLINE = ERROR_LINE()
,@ERRORPROCEDURE = ISNULL(ERROR_PROCEDURE(), '-')
,@ERRORMESSAGETEXT = ERROR_MESSAGE()

SET @ERRORIND = 1
END CATCH

IF (@ERRORIND = 1)
BEGIN
IF CURSOR_STATUS('variable', '@QUERY_CUR') IN (0,1)
CLOSE @QUERY_CUR
IF CURSOR_STATUS('variable', '@QUERY_CUR') = -1
DEALLOCATE @QUERY_CUR

DECLARE
@ADJUSTEDERRORSEVERITY INT

SET @ADJUSTEDERRORSEVERITY = CASE
WHEN @ERRORSEVERITY &gt; 18 THEN 18
ELSE @ERRORSEVERITY
END

IF @DEBUG = 0
PRINT @SQL

RAISERROR (@ERRORMESSAGETEXT, @ADJUSTEDERRORSEVERITY, 1
,@ERRORNUMBER
,@ERRORSEVERITY
,@ERRORSTATE
,@ERRORPROCEDURE
,@ERRORLINE
,@ERRORMESSAGETEXT
)
END
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.PMApplyActionsToDb'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.PMApplyActionsToDb AS RETURN 1')
END
GO

/******************************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: PMApplyActionsToDb */
/* INPUT PARAMETERS: */
/* @RULEDESCRIPTION - rule description */
/* @CLIENT - client event flag : 0 - server event 1 - client event */
/* @DBID - seviewer database id. SEviewerDb primary key */
/* @DEBUG - 0-trace information will be not print */
/* 1-trace information will be print */
/* OUTPUT PARAMETERS: */
/* @PROGRESS - rows affected */
/* DESCRIPTION: */
/* Update records corresponding rule. */
/* It is need external temporary tables #QUERYTEXT and #RESULTTABLE for execute. */
/* #QUERYTEXT table is used for cache sql query (decrease execution count of xml operations). */
/* #RESULT table contains event id of records of event table that will be updated */
/******************************************************************************************************/
alter PROCEDURE [APM].[PMApplyActionsToDb]
@RULEDESCRIPTION nvarchar(max)
,@CLIENT bit
,@DBID int
,@DEBUG bit = 0
,@PROGRESS int OUTPUT
AS
BEGIN
SET NOCOUNT ON;

DECLARE
@ERRORIND BIT
,@ERRORMESSAGE NVARCHAR(4000)
,@ERRORNUMBER INT
,@ERRORSEVERITY INT
,@ERRORSTATE INT
,@ERRORLINE INT
,@ERRORPROCEDURE SYSNAME
,@ERRORMESSAGETEXT NVARCHAR(4000)

SET @ERRORIND = 0

BEGIN TRY

DECLARE
@SQL nvarchar(max) -- update sql

-- check cache
IF NOT EXISTS(SELECT * FROM #QUERYTEXT WHERE UPDATESQL = 1)
BEGIN
-- update query not found
-- create update query

DECLARE
@ACTIONPARAMS nvarchar(max) -- action parameter and database id parameter
,@ACTIONPARAMSVALUES nvarchar(max) -- action parameter value and database id parameter value
,@ACTIONPARAMETER nvarchar(50) -- action parameter
,@ACTIONFIELD nvarchar(50) -- action field
,@ACTIONENTITY nvarchar(max) -- action entity (table/view or stored proc)
,@ACTION_CURSOR CURSOR -- action cursor for fetching action parameters, etc

DECLARE
@SETEXPRESSION nvarchar(max)
,@PARAMS nvarchar(MAX)
,@PARAMSVALUES nvarchar(max)

-- get action cursor corresponding rule
EXEC APM.PMActionQuery @RULEDESCRIPTION, @CLIENT, @DBID, 0, @ACTION_CURSOR OUTPUT

-- initialize action parameters
SELECT @SETEXPRESSION = N'', @PARAMS = N'', @PARAMSVALUES = N''

-- fetch action parameters
FETCH NEXT FROM @ACTION_CURSOR
INTO @ACTIONPARAMETER, @ACTIONFIELD, @ACTIONPARAMS, @ACTIONPARAMSVALUES, @ACTIONENTITY

WHILE @@FETCH_STATUS = 0
BEGIN
SELECT

--create 'set' clause for update sql ([action field] = [action parameter])
@SETEXPRESSION = @SETEXPRESSION + REPLACE(REPLACE(REPLACE(CONVERT(nvarchar(max),N'{0}e.{1}={2}'),
N'{0}',CASE WHEN LEN(@SETEXPRESSION) &gt; 0 THEN N',' ELSE N'' END),
N'{1}',@ACTIONFIELD),
N'{2}',@ACTIONPARAMETER)

--create parameters for update sql
,@PARAMS = @PARAMS +
REPLACE(REPLACE(CONVERT(nvarchar(max),N'{0}{1}'),
N'{0}',CASE WHEN LEN(@PARAMS) &gt; 0 THEN N',' ELSE N'' END),
N'{1}', @ACTIONPARAMS)
--create parameter values for update sql
,@PARAMSVALUES = @PARAMSVALUES + REPLACE(REPLACE(CONVERT(nvarchar(max),N'{0}{1}'),
N'{0}',CASE WHEN LEN(@PARAMSVALUES) &gt; 0 THEN N',' ELSE N'' END),
N'{1}',@ACTIONPARAMSVALUES)
--fetch next action parameters. Now should be empty because use only one action.
FETCH NEXT FROM @ACTION_CURSOR
INTO @ACTIONPARAMETER, @ACTIONFIELD, @ACTIONPARAMS, @ACTIONPARAMSVALUES, @ACTIONENTITY
END
CLOSE @ACTION_CURSOR
DEALLOCATE @ACTION_CURSOR

DECLARE
@COMMAND nvarchar(max) -- update command
,@ROWSAFFECTED int -- rows affected

-- create update command using external temporary table
SELECT @COMMAND =
REPLACE(REPLACE(CONVERT(nvarchar(max),
N'UPDATE e
SET {0}
OUTPUT INSERTED.EventId, INSERTED.pmstatus INTO #STATUSTABLE
FROM APM.{1} e
JOIN #RESULTTABLE r ON r.EVENTID = e.EVENTID
SET @ROWSAFFECTED = @@ROWCOUNT
'),
N'{0}', @SETEXPRESSION),
N'{1}', @ACTIONENTITY)
-- add sp_execute call for execution update command
SELECT @SQL = REPLACE(REPLACE(REPLACE(CONVERT(nvarchar(max),N'exec sp_executesql N''{0}'', N''{1}'', {2}'),
N'{0}',@COMMAND),
N'{1}',@PARAMS + N',@ROWSAFFECTED int OUTPUT'),
N'{2}',@PARAMSVALUES + N',@ROWSAFFECTED=@ROWSAFFECTED OUTPUT')

IF @DEBUG = 1
PRINT @SQL

-- insert sql command into cache
INSERT #QUERYTEXT(SQLTEXT, UPDATESQL, PMSTATUS) SELECT @SQL, 1, @ACTIONPARAMSVALUES
END

DECLARE
@PMSTATUS nvarchar(MAX)

-- get query from cache
SELECT TOP (1) @SQL = SQLTEXT, @PMSTATUS = PMSTATUS FROM #QUERYTEXT WHERE UPDATESQL = 1

CREATE TABLE #STATUSTABLE (EVENTID int, PMSTATUS tinyint)

-- execute update events corresponding rule
EXEC sp_executesql @SQL,N'@ROWSAFFECTED int OUTPUT',@ROWSAFFECTED = @ROWSAFFECTED OUTPUT

IF @DEBUG = 1
PRINT N'Rows affected: ' + CAST(@ROWSAFFECTED AS nvarchar(10))

IF @ROWSAFFECTED &gt; 0
BEGIN
--create event trace
EXEC APM.PMCREATEEVENTTRACES @CLIENT = @CLIENT, @DATA = @RULEDESCRIPTION
END
--save rows affected
SELECT @PROGRESS = @ROWSAFFECTED
END TRY
BEGIN CATCH
IF (@@TRANCOUNT &gt; 0)
ROLLBACK TRAN

SELECT
@ERRORNUMBER = ERROR_NUMBER()
,@ERRORSEVERITY = ERROR_SEVERITY()
,@ERRORSTATE = ERROR_STATE()
,@ERRORLINE = ERROR_LINE()
,@ERRORPROCEDURE = ISNULL(ERROR_PROCEDURE(), '-')
,@ERRORMESSAGETEXT = ERROR_MESSAGE()

SET @ERRORIND = 1
END CATCH
IF (@ERRORIND = 1)
BEGIN
IF CURSOR_STATUS('variable', '@ACTION_CURSOR') IN (0,1)
CLOSE @ACTION_CURSOR
IF CURSOR_STATUS('variable', '@ACTION_CURSOR') = -1
DEALLOCATE @ACTION_CURSOR
DECLARE
@ADJUSTEDERRORSEVERITY INT

SET @ADJUSTEDERRORSEVERITY = CASE
WHEN @ERRORSEVERITY &gt; 18 THEN 18
ELSE @ERRORSEVERITY
END

IF @DEBUG = 0
PRINT @SQL

RAISERROR (@ERRORMESSAGETEXT, @ADJUSTEDERRORSEVERITY, 1
,@ERRORNUMBER
,@ERRORSEVERITY
,@ERRORSTATE
,@ERRORPROCEDURE
,@ERRORLINE
,@ERRORMESSAGETEXT
)
END
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.PMApplyToDbForEventType'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.PMApplyToDbForEventType AS RETURN 1')
END
GO

/******************************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: PMApplyToDbForEventType */
/* INPUT PARAMETERS: */
/* @CALCULATETOTAL - calculate total flag (1- it is need to calculate count of records */
/* 0- it is need to fetch records) */
/* @CLIENT - client event flag : 0 - server event 1 - client event */
/* @DBID - seviewer database id. SEviewerDb primary key */
/* @RULEDESCRIPTION - rule description */
/* @ROWSPERITERATION - number of records that is need to fetch */
/* @ROWSPERREQUEST - number of records that is need to process for one call of stored */
/* - procedure */
/* @DEBUG - 0-trace information will be not print */
/* 1-trace information will be print */
/* OUTPUT PARAMETERS: */
/* @ROWSAFFECTED - rows affected if calculate total flag equal zero */
/* @TOTAL - calculate row count if calculate total flag equal one */
/* DESCRIPTION: */
/* Calculate total records or update records that will be apply by rule. */
/******************************************************************************************************/
alter PROCEDURE [APM].[PMApplyToDbForEventType]
@CALCULATETOTAL bit
,@CLIENT bit
,@DBID int
,@RULEDESCRIPTION nvarchar(MAX)
,@ROWSPERITERATION int
,@ROWSPERREQUEST int
,@DEBUG bit
,@ROWSAFFECTED int OUTPUT
,@TOTAL int OUTPUT
AS
BEGIN
SET NOCOUNT ON;

DECLARE
@ERRORIND BIT
,@ERRORMESSAGE NVARCHAR(4000)
,@ERRORNUMBER INT
,@ERRORSEVERITY INT
,@ERRORSTATE INT
,@ERRORLINE INT
,@ERRORPROCEDURE SYSNAME
,@ERRORMESSAGETEXT NVARCHAR(4000)

SET @ERRORIND = 0

BEGIN TRY

-- Initialize output parameters
SELECT @TOTAL = 0, @ROWSAFFECTED = 0

-- It is need external temporary tables for execute.
--It is need for saving results
CREATE TABLE #RESULTTABLE (EVENTID int)
--It is need for cache sql query
CREATE TABLE #QUERYTEXT (SQLTEXT nvarchar(max), UPDATESQL bit, PMSTATUS nvarchar(MAX))

IF @CALCULATETOTAL = 1
BEGIN
--Calculate total
EXEC APM.PMQueryForRule
@RULEDESCRIPTION = @RULEDESCRIPTION
,@CLIENT = @CLIENT
,@DBID = @DBID
,@CALCULATETOTAL = @CALCULATETOTAL
,@ROWSPERITERATION = @ROWSPERITERATION
,@DEBUG = @DEBUG
--EventId contains result
SELECT @TOTAL = EVENTID FROM #RESULTTABLE
END
IF @CALCULATETOTAL = 0
BEGIN
--Update records
DECLARE @CURRENTAFFECTED int
--Iteration by "rows per iteration"
WHILE @ROWSAFFECTED &lt; @ROWSPERREQUEST
BEGIN
--Fill #RESULT table
EXEC APM.PMQueryForRule
@RULEDESCRIPTION = @RULEDESCRIPTION
,@CLIENT = @CLIENT
,@DBID = @DBID
,@CALCULATETOTAL = @CALCULATETOTAL
,@ROWSPERITERATION = @ROWSPERITERATION
,@DEBUG = @DEBUG
-- #RESULT table contains set of eventId referencing to the event records that will be updated
EXEC APM.PMApplyActionsToDb
@RULEDESCRIPTION = @RULEDESCRIPTION
,@CLIENT = @CLIENT
,@DBID = @DBID
,@DEBUG = @DEBUG
,@PROGRESS = @CURRENTAFFECTED OUTPUT

-- update rows affected counter
SELECT @ROWSAFFECTED = @ROWSAFFECTED + @CURRENTAFFECTED

--get out if current rows affected less rows per iteration because rows per iteration records should be updated
IF @CURRENTAFFECTED &lt; @ROWSPERITERATION
BREAK
-- truncate temporary table for next iteration
TRUNCATE TABLE #RESULTTABLE
END
END
END TRY
BEGIN CATCH
IF (@@TRANCOUNT &gt; 0)
ROLLBACK TRAN

SELECT
@ERRORNUMBER = ERROR_NUMBER()
,@ERRORSEVERITY = ERROR_SEVERITY()
,@ERRORSTATE = ERROR_STATE()
,@ERRORLINE = ERROR_LINE()
,@ERRORPROCEDURE = ISNULL(ERROR_PROCEDURE(), '-')
,@ERRORMESSAGETEXT = ERROR_MESSAGE()

SET @ERRORIND = 1
END CATCH
IF (@ERRORIND = 1)
BEGIN
DECLARE
@ADJUSTEDERRORSEVERITY INT

SET @ADJUSTEDERRORSEVERITY = CASE
WHEN @ERRORSEVERITY &gt; 18 THEN 18
ELSE @ERRORSEVERITY
END


RAISERROR (@ERRORMESSAGETEXT, @ADJUSTEDERRORSEVERITY, 1
,@ERRORNUMBER
,@ERRORSEVERITY
,@ERRORSTATE
,@ERRORPROCEDURE
,@ERRORLINE
,@ERRORMESSAGETEXT
)
END
END
GO

IF (OBJECTPROPERTY(OBJECT_ID('APM.PMApplyToDb'), 'IsProcedure') IS NULL)
BEGIN
EXECUTE ('CREATE PROCEDURE APM.PMApplyToDb AS RETURN 1')
END
GO

/******************************************************************************************************/
/* OBJECT: Stored Procedure */
/* NAME: PMApplyToDb */
/* INPUT PARAMETERS: */
/* @CALCULATETOTAL - calculate total flag (1- it is need to calculate count of records */
/* 0- it is need to fetch records) */
/* @RULEDESCRIPTION - rule description */
/* @ROWSPERITERATION - number of records that is need to fetch */
/* @ROWSPERREQUEST - number of records that is need to process for one call of stored */
/* @TRACELEVEL - trace level (4 - detail trace, other - reserved) */
/* OUTPUT PARAMETERS: */
/* @ROWSAFFECTED - rows affected if calculate total flag equal zero */
/* @TOTAL - calculate row count if calculate total flag equal one */
/* DESCRIPTION: */
/* Calculate total records or update records that will be apply by rule. It call internal stored */
/* procedure for server and client events. */
/******************************************************************************************************/
alter PROCEDURE [APM].[PMApplyToDb]
@CALCULATETOTAL bit
,@RULEDESCRIPTION nvarchar(MAX)
,@ROWSPERITERATION int
,@ROWSPERREQUEST int
,@TRACELEVEL int
,@ROWSAFFECTED int OUTPUT
,@TOTAL int OUTPUT
AS
BEGIN
SET NOCOUNT ON

DECLARE
@DEBUG bit -- debug flag (1 - debug, 0 - without debug)
,@SERVERROWSAFFECTED int -- server event records affected
,@SERVERTOTAL int -- server total events (when calculate flag equal one)
,@CLIENTROWSAFFECTED int -- client event records affected
,@CLIENTTOTAL int -- client total events (when calculate flag equal one)
,@DBID int -- seviewer database primary key (seviewerdb table)
,@DBGUID uniqueidentifier -- seviewer database identifier (only records from this seviewer database will be calculated or updated)
,@RULE xml -- untype xml contains rule description

-- implicit conversion to xml
SET @RULE = @RULEDESCRIPTION

--get seviewer database unique identifier
SELECT @DBGUID = @RULE.value('(/rule/@dbid)[1]', 'uniqueidentifier')
--get corresponding seviewer db primary key
SELECT @DBID = SEVIEWERDBID from APM.SEVIEWERDB (NOLOCK)
WHERE DATABASEID = @DBGUID
--database id is exist?
IF @@ROWCOUNT = 0
BEGIN
--No, raise exception
DECLARE
@DATABASEGUIDSTR nvarchar(50)
SELECT @DATABASEGUIDSTR = CAST(@DBGUID as nvarchar(50))
RAISERROR (N'DATABASE Id=''%s'' is not found', 16, 1, @DATABASEGUIDSTR)
RETURN
END

-- debug mode ? (trace level should be equal 4)
SELECT @DEBUG =
CASE
WHEN @TRACELEVEL = 4 THEN 1 ELSE 0
END

-- calculate or update server events
EXECUTE APM.PMApplyToDbForEventType @CALCULATETOTAL = @CALCULATETOTAL, -- bit
@CLIENT = 0, -- bit
@DBID = @DBID, -- int
@RULEDESCRIPTION = @RULEDESCRIPTION, -- nvarchar(max)
@ROWSPERITERATION = @ROWSPERITERATION, -- int
@ROWSPERREQUEST = @ROWSPERREQUEST, -- int
@DEBUG = @DEBUG, -- bit
@ROWSAFFECTED = @SERVERROWSAFFECTED OUTPUT, -- rows affected
@TOTAL = @SERVERTOTAL OUTPUT --total count (if calculate total flag equal 1)

-- calculate or update client events
EXECUTE APM.PMApplyToDbForEventType @CALCULATETOTAL = @CALCULATETOTAL, -- bit
@CLIENT = 1, -- bit
@DBID = @DBID, -- int
@RULEDESCRIPTION = @RULEDESCRIPTION, -- nvarchar(max)
@ROWSPERITERATION = @ROWSPERITERATION, -- int
@ROWSPERREQUEST = @ROWSPERREQUEST, -- int
@DEBUG = @DEBUG, -- bit
@ROWSAFFECTED = @CLIENTROWSAFFECTED OUTPUT, -- rows affected
@TOTAL = @CLIENTTOTAL OUTPUT --total count (if calculate total flag equal 1)

-- update counters
SELECT
@TOTAL = COALESCE(@CLIENTTOTAL,0) + COALESCE(@SERVERTOTAL,0)
,@ROWSAFFECTED = COALESCE(@CLIENTROWSAFFECTED,0) + COALESCE(@SERVERROWSAFFECTED,0)
END
GO
</Upgrade>
</DataWarehouseDataSet>