diff --git a/C4IT_DataHistoryProvider_Base/Publish/F4SD-Cockpit-Server.dll b/C4IT_DataHistoryProvider_Base/Publish/F4SD-Cockpit-Server.dll
index 88642b0..909a9bd 100644
Binary files a/C4IT_DataHistoryProvider_Base/Publish/F4SD-Cockpit-Server.dll and b/C4IT_DataHistoryProvider_Base/Publish/F4SD-Cockpit-Server.dll differ
diff --git a/C4IT_DataHistoryProvider_Test/Config/F4SD-CopyTemplate-Configuration.xml b/C4IT_DataHistoryProvider_Test/Config/F4SD-CopyTemplate-Configuration.xml
index 88f2e2e..99bf31c 100644
--- a/C4IT_DataHistoryProvider_Test/Config/F4SD-CopyTemplate-Configuration.xml
+++ b/C4IT_DataHistoryProvider_Test/Config/F4SD-CopyTemplate-Configuration.xml
@@ -1,44 +1,67 @@
-
-
- Ticket-Information
- Transfers the relevant information for ticket creation to the clipboard.
- Überträgt die relevanten Informationen für eine Ticket Erstellung in den Zwischenspeicher.
-
- %DeviceName.Label% %DeviceName.Value%
-%UserFullName.Label% %UserFullName.Value%
-%UserAccount.Label% %UserAccount.Value%
-%DeviceModel.Label% %DeviceModel.Value%
-%OsInfo.Label% %OsInfo.Value%
-%IpAddress.Label% %IpAddress.Value%
-%LastBoot.Label% %LastBoot.Value%
-%LastSeen.Label% %LastSeen.Value%
- <table border="1" cellpadding="5,1,5,1"><tbody>
-<tr><td><em>%DeviceName.Label%</em></td><td style="color: #0000ff;">%DeviceName.Value%</td></tr>
-<tr><td><em>%UserFullName.Label%</em></td><td>%UserFullName.Value%</td></tr>
-<tr><td><em>%UserAccount.Label%</em></td><td>%UserAccount.Value%</td></tr>
-<tr><td><em>%OsInfo.Label%</em></td><td>%OsInfo.Value%</td></tr>
-<tr><td><em>%IpAddress.Label%</em></td><td>%IpAddress.Value%</td></tr>
-<tr><td><em>%LastBoot.Label%</em></td><td>%LastBoot.Value%</td></tr>
-<tr><td><em>%LastSeen.Label%</em></td><td>%LastSeen.Value%</td></tr>
-</tbody></table>
+
+
+ Ticket-Information-Computer
+ Transfers the relevant information for ticket creation to the clipboard.
+ Überträgt die relevanten Informationen für eine Ticket Erstellung in den Zwischenspeicher.
+
+
+ %DeviceName.Label% %DeviceName.Value%
+ %UserFullName.Label% %UserFullName.Value%
+ %UserAccount.Label% %UserAccount.Value%
+ %DeviceModel.Label% %DeviceModel.Value%
+ %OsInfo.Label% %OsInfo.Value%
+ %IpAddress.Label% %IpAddress.Value%
+ %LastBoot.Label% %LastBoot.Value%
+ %LastSeen.Label% %LastSeen.Value%
+
+
+ <table border="1" cellpadding="5,1,5,1"><tbody>
+ <tr><td><em>%DeviceName.Label%</em></td><td style="color: #0000ff;">%DeviceName.Value%</td></tr>
+ <tr><td><em>%UserFullName.Label%</em></td><td>%UserFullName.Value%</td></tr>
+ <tr><td><em>%UserAccount.Label%</em></td><td>%UserAccount.Value%</td></tr>
+ <tr><td><em>%OsInfo.Label%</em></td><td>%OsInfo.Value%</td></tr>
+ <tr><td><em>%IpAddress.Label%</em></td><td>%IpAddress.Value%</td></tr>
+ <tr><td><em>%LastBoot.Label%</em></td><td>%LastBoot.Value%</td></tr>
+ <tr><td><em>%LastSeen.Label%</em></td><td>%LastSeen.Value%</td></tr>
+ </tbody></table>
+
+
+
+ Ticket Information VM
+ Transfers the relevant information for ticket creation to the clipboard.
+ Überträgt die relevanten Informationen für eine Ticket Erstellung in den Zwischenspeicher.
+
+
+ %VirtualSessionName.Label% %VirtualSessionName.Value%
+ %VirtualSessionStatus.Label% %VirtualSessionStatus.Value%
+ %HostedMachine.Label% %HostedMachine.Value%
+ %DeviceName.Label% %DeviceName.Value%
+
+
+ <table border="1" cellpadding="5,1,5,1"><tbody>
+ <tr><td><em>%VirtualSessionName.Label%</em></td><td style="color: #0000ff;">%VirtualSessionName.Value%</td></tr>
+ <tr><td><em>%VirtualSessionStatus.Label%</em></td><td>%VirtualSessionStatus.Value%</td></tr>
+ <tr><td><em>%HostedMachine.Label%</em></td><td>%HostedMachine.Value%</td></tr>
+ </tbody></table>
+
Computer Name
-
+
- %DeviceName.Value%
+ %DeviceName.Label% %DeviceName.Value%
Anwendername
- %UserFullName.Value%
+ %UserFullName.Label% %UserFullName.Value%
Anwender Account
- %UserAccount.Value%
+ %UserAccount.Label% %UserAccount.Value%
\ No newline at end of file
diff --git a/C4IT_DataHistoryProvider_Test/Config/F4SD-DataClusters-Configuration.xml b/C4IT_DataHistoryProvider_Test/Config/F4SD-DataClusters-Configuration.xml
index f989495..8223146 100644
--- a/C4IT_DataHistoryProvider_Test/Config/F4SD-DataClusters-Configuration.xml
+++ b/C4IT_DataHistoryProvider_Test/Config/F4SD-DataClusters-Configuration.xml
@@ -1378,6 +1378,14 @@
+
diff --git a/C4IT_DataHistoryProvider_Test/Config/F4SD-HealthCard-Configuration.xml b/C4IT_DataHistoryProvider_Test/Config/F4SD-HealthCard-Configuration.xml
index 9ee101f..db0156b 100644
--- a/C4IT_DataHistoryProvider_Test/Config/F4SD-HealthCard-Configuration.xml
+++ b/C4IT_DataHistoryProvider_Test/Config/F4SD-HealthCard-Configuration.xml
@@ -1377,10 +1377,20 @@
Session
-
- Session Status
+
+ DNS Name
+
+
+ Domäne Name
+
+
+ Hosted Machine
+
+
+ Gerätname
+
@@ -1390,7 +1400,7 @@
-
+
@@ -1493,14 +1503,11 @@
-
-
-
Benutzer-Informationen
@@ -1521,11 +1528,7 @@
Desktopgruppe
-
-
- Session Id
-
Session-Informationen
@@ -1538,7 +1541,7 @@
Enddatum
-
+
Verbindungsstatus
@@ -1551,7 +1554,6 @@
Anonym
-
Verbindung-Informationen
@@ -1585,12 +1587,10 @@
Profilladezeit
-
Host-Informationen
-
Hostname
@@ -1613,12 +1613,28 @@
Wartungsmodus aktiv
-
+
+
+ Host Nutzung-Informationen
+
+
+ CPU Auslastung
+
+
+ RAM/Arbeitsspeicher Auslastung
+
+
+ Speicher Auslastung
+
+
+ Aktuelle Sitzungsanzahl
+
+
Host Nutzung-Informationen
-
+
CPU Auslastung
@@ -1632,15 +1648,12 @@
-
Netzwerk Performance
Information about network performance
Informationen über die Netzwerk Performance
-
-
Genutzte Input Bandbreite
Used Input Bandwidth in this Citrix session.
@@ -1656,7 +1669,6 @@
-
Verfügbare Output Bandbreite
Output Bandwidth available in this Citrix session.
@@ -1677,7 +1689,6 @@
-
Genutzte Output Bandbreite
Output Bandwidth used in this Citrix session.
@@ -1687,16 +1698,22 @@
+
-
HDX Performance
Information about HDX Performance
Informationen über HDX Performance
-
-
-
Input FPS
Frame rate per second transmitted from the server to the client.
@@ -1712,7 +1729,6 @@
-
Output FPS
The frame rate the client displays on the screen after processing.
@@ -1728,7 +1744,6 @@
-
FPS (Bilder pro Sekunde)
Measured FPS (Frame per second) in this Citrix session.
@@ -1749,14 +1764,11 @@
-
-
Session Latenz Performance
Information about session latencies
Informationen über die Session Latenz
-
ICA RTT
Measured response time (Round Trip Time) in this Citrix session.
@@ -1772,7 +1784,6 @@
-
ICA Latenz
Measured ICA Latency in this Citrix session.
@@ -1788,7 +1799,6 @@
-
Server Latenz
Measured Server Latency in this Citrix session.
@@ -1804,7 +1814,6 @@
-
Client Latenz
Measured Client Latency in this Citrix session.
@@ -1818,9 +1827,8 @@
Nutzung
-
+
-
WAN Latenz
Measured WAN Latency in this Citrix session.
@@ -1834,9 +1842,8 @@
Nutzung
-
+
-
DC (Delivery Controller) Latenz
Measured Delivery Controller Latency in this Citrix session.
@@ -1852,7 +1859,6 @@
-
diff --git a/C4IT_DataHistoryProvider_Test/Config/F4SD-Infrastructure-Configuration.xml b/C4IT_DataHistoryProvider_Test/Config/F4SD-Infrastructure-Configuration.xml
index 2447291..04e2d79 100644
--- a/C4IT_DataHistoryProvider_Test/Config/F4SD-Infrastructure-Configuration.xml
+++ b/C4IT_DataHistoryProvider_Test/Config/F4SD-Infrastructure-Configuration.xml
@@ -77,7 +77,7 @@
- onPremisesExtensionAttributes/extensionAttribute8 in ('C4IT', 'TS4U') and userType eq 'member' and accountEnabled eq true
+ onPremisesExtensionAttributes/extensionAttribute8 in ('C4IT', 'TS4U') and userType eq 'member' and accountEnabled eq true
diff --git a/C4IT_DataHistoryProvider_Test/Config/F4SD-Infrastructure-Configuration.xsd b/C4IT_DataHistoryProvider_Test/Config/F4SD-Infrastructure-Configuration.xsd
index ce9c2fc..3387100 100644
--- a/C4IT_DataHistoryProvider_Test/Config/F4SD-Infrastructure-Configuration.xsd
+++ b/C4IT_DataHistoryProvider_Test/Config/F4SD-Infrastructure-Configuration.xsd
@@ -1,47 +1,47 @@
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
@@ -75,117 +75,117 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -210,137 +210,137 @@
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -352,203 +352,211 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
@@ -569,7 +577,7 @@
-
+
@@ -616,25 +624,25 @@
-
+
-
-
+
+
-
-
-
-
-
+
+
+
+
+
diff --git a/F4SD-Cockpit-ServerCore/DataHistoryCollector.cs b/F4SD-Cockpit-ServerCore/DataHistoryCollector.cs
index a204929..543227b 100644
--- a/F4SD-Cockpit-ServerCore/DataHistoryCollector.cs
+++ b/F4SD-Cockpit-ServerCore/DataHistoryCollector.cs
@@ -520,8 +520,12 @@ namespace C4IT.DataHistoryProvider
if(HasIntuneConfig)
{
Connectors.Add(enumDataHistoryOrigin.Intune, ActiveDirectory);
- RegisterSearchRelationProvider(ActiveDirectory);
+
}
+ //if (HasIntuneConfig && HasMobileDeviceConfig)
+ //{
+ // RegisterSearchRelationProvider(ActiveDirectory);
+ //}
// do the post configuration tasks afer the infrastructure was loaded
DoProcessUiMessage(1, "processing post configuration tasks");
@@ -6491,6 +6495,34 @@ namespace C4IT.DataHistoryProvider
return null;
}
+ public cCollectorStatusInfo GetCollectorStatus(cF4sdWebRequestInfo requestInfo)
+ {
+ MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
+ try
+ {
+ var _cfgInfrastructure = new cDataHistoryConfigInfrastructure();
+ _cfgInfrastructure.LoadFromFile(out var PMs);
+ var retVal = new cCollectorStatusInfo();
+
+ retVal.HasM42Config = _cfgInfrastructure.M42Wpm != null;
+ retVal.HasIntuneConfig = (_cfgInfrastructure.AzureTenants?.Values.Any(t => t.ScanIntuneDevices) == true);
+ retVal.HasMobileDeviceConfig = (_cfgInfrastructure.AzureTenants?.Values.Any(t => t.WithMobileDevices) == true);
+ retVal.HasCitrixConfig = (InfrastructureConfig.Citrix != null);
+
+ return retVal;
+ }
+ catch (Exception E)
+ {
+ LogException(E);
+ }
+ finally
+ {
+ if (CM != null) LogMethodEnd(CM);
+ }
+
+ return null;
+ }
+
public override async Task ValidateTokenAsync(cF4SDTokenRegistration TokenRegistration, cF4sdWebRequestInfo requestInfo, int LogDeep, CancellationToken Token)
{
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
@@ -6723,6 +6755,14 @@ namespace C4IT.DataHistoryProvider
}
}
+ public class cCollectorStatusInfo
+ {
+ public bool HasM42Config;
+ public bool HasIntuneConfig;
+ public bool HasMobileDeviceConfig;
+ public bool HasCitrixConfig;
+ }
+
public class cDataHistorySHistoryScanInfo
{
public Guid ID;
diff --git a/F4SD-Cockpit-ServerCore/DataHistoryCollectorActiveDirectory.cs b/F4SD-Cockpit-ServerCore/DataHistoryCollectorActiveDirectory.cs
index 018b2fe..e048cf8 100644
--- a/F4SD-Cockpit-ServerCore/DataHistoryCollectorActiveDirectory.cs
+++ b/F4SD-Cockpit-ServerCore/DataHistoryCollectorActiveDirectory.cs
@@ -1545,10 +1545,10 @@ namespace C4IT.DataHistoryProvider
var strUrl = string.Format(constMsGraphUserList, constMsGraphUserPaging);
- if (!string.IsNullOrEmpty(Tenant.ScanFilter))
- strUrl += " and (" + Tenant.ScanFilter + ")";
+ if (!string.IsNullOrEmpty(Tenant.ScanFilterUser))
+ strUrl += " and (" + Tenant.ScanFilterUser + ")";
- var Result = await MsGraph.RequestListAsync(strUrl, UseBeta: false, retryForbidden: false, loadPaged: true, ConsistencyLevelEventual: Tenant.UseConsistencyLevelEventual);
+ var Result = await MsGraph.RequestListAsync(strUrl, UseBeta: Tenant.UseBetaUserFilter, retryForbidden: false, loadPaged: true, ConsistencyLevelEventual: Tenant.ConsistencyLevelEventualUserFilter);
var Count = 0;
var Updated = 0;
@@ -2058,7 +2058,7 @@ namespace C4IT.DataHistoryProvider
try
{
List Ids = await _collector.getConnectorIdList(ids.ToList(), token, null, 0);
- List relations = await GetMobileDeviceAsync(Ids, token, null);
+ List relations = await GetUserMobileDevicesAsync(Ids, token, null);
return new cF4sdStagedSearchResultRelations() { Relations = relations };
}
catch (Exception ex)
@@ -2505,7 +2505,7 @@ namespace C4IT.DataHistoryProvider
return null;
}
- public async Task> GetMobileDeviceAsync(List UserId, CancellationToken Token, cF4sdWebRequestInfo requestInfo)
+ public async Task> GetUserMobileDevicesAsync(List UserId, CancellationToken Token, cF4sdWebRequestInfo requestInfo)
{
MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
try
@@ -2513,34 +2513,23 @@ namespace C4IT.DataHistoryProvider
string userIds = string.Join(",", UserId.Where(u => !string.IsNullOrWhiteSpace(u?.intuneId.ToString())).Select(u => u.intuneId));
var tenantId = UserId?.FirstOrDefault(u => u?.tenantId != Guid.Empty)?.tenantId ?? Guid.Empty;
-
- var userId_str = "ef333f80-0ae1-40b3-826f-2dc69c80c1f0";
- var intuneId = new Guid(userId_str);
- var strUrl = string.Format(constMsGraphManagedMobileDeviceList, intuneId);
+
+ var strUrl = string.Format(constMsGraphManagedMobileDeviceList, userIds);
var MsGraph = await GetGraphForTenantAsync(tenantId, true);
if (MsGraph == null)
return null;
-
- // Schritt 1: Abrufen der Recovery-Key IDs
+
var Result = await MsGraph.RequestListAsync(strUrl, UseBeta: false, retryForbidden: false);
if (Result != null == Result.Count > 0)
{
var searchResult = new List(Result.Count);
- //double _sumDuration = 0;
+
foreach (var Entry in Result)
{
var endDate = DateTime.MinValue;
if (!DateTime.TryParse(Entry.Result.lastSyncDateTime?.ToString(), out endDate))
endDate = DateTime.UtcNow;
-
- //var startDate = DateTime.MinValue;
- //if (!DateTime.TryParse(Entry.Result.StartDate?.ToString(), out startDate))
- // startDate = DateTime.UtcNow;
-
- //TimeSpan _duration = endDate - startDate;
- //_sumDuration += _duration.TotalSeconds;
-
var searchInfo = new cF4sdApiSearchResultRelation()
{
diff --git a/F4SD-Cockpit-ServerCore/DataHistoryCollectorCitrix.cs b/F4SD-Cockpit-ServerCore/DataHistoryCollectorCitrix.cs
index 1df4977..f1d99c7 100644
--- a/F4SD-Cockpit-ServerCore/DataHistoryCollectorCitrix.cs
+++ b/F4SD-Cockpit-ServerCore/DataHistoryCollectorCitrix.cs
@@ -45,6 +45,8 @@ namespace C4IT.DataHistoryProvider
public const string constCitrixSessionMachine = "monitorodata/Sessions?$select=SessionKey&$filter=SessionKey eq {0}&$expand=Machine($expand=CurrentLoadIndex,Catalog,DesktopGroup($select=Name)),Machine";
public const string constCitrixSessionCurrentConnection = "monitorodata/Sessions?$select=SessionKey&$filter=SessionKey eq {0}&$expand=CurrentConnection,LogOnMetrics";
public const string constCitrixSessionConnections = "monitorodata/Sessions?$select=SessionKey&$filter=SessionKey eq {0}&$expand=Connection";
+ public const string constCitrixSessionLogInSummaries = "monitorodata/Sessions?$filter=UserId in ({0})$select=Id,StartDate&$expand=User($select=UserName),LogOnSummaries($select=LogOnDuration,AuthenticationDuration,BrokingDuration,ProfileLoadDuration,GpoProcessingDuration,InteractiveSessionDuration)";
+ public const string constCitrixSessionLogInSummaries2 = "monitorodata/LogOnSummaries?$expand=Session($expand=User)&$filter=UserId eq {0}";
public const string constCitrixUserConnections = "monitorodata/Sessions?$filter=UserId in ({0})&$expand=Connection";
public const string constCitrixSessionUser = "monitorodata/Sessions?$select=SessionKey&$filter=SessionKey eq {0}&$expand=User";
public const string constCitrixSessionLogoff = "cvad/manage/Sessions/{0}/$logoff";
@@ -55,6 +57,7 @@ namespace C4IT.DataHistoryProvider
public const string constTableNameSessionConnection = "citrix-session-connection";
public const string constTableNameSessionCurrentConnection = "citrix-session-currentConnection";
public const string constTableNameSessionMetrics = "citrix-session-metrics";
+ public const string constTableNameSessionStateMetrics = "citrix-connectionState-metrics";
public const string constTableNameSessionUser = "citrix-session-user";
public const string constTableNameSessionDetailsIcaRttMS = "citrix-session-details-icaRttMS";
public const string constTableNameSessionDetailsIcaLatency = "citrix-session-details-icaLatency";
@@ -327,7 +330,7 @@ namespace C4IT.DataHistoryProvider
return null;
var res = await citrixCommunication.RequestListAsync(strUrl, retryForbidden: false);
- if (res != null)
+ if (res != null == res.Count > 0)
{
JObject sessionInfos = res[0].Result;
var retVal = new cF4SDHealthCardRawData.cHealthCardTable()
@@ -339,7 +342,13 @@ namespace C4IT.DataHistoryProvider
TableType = eDataHistoryTableType.Static
};
- var dicVals = new List>();
+ foreach (var Entry in res) {
+
+
+
+ }
+
+ var dicVals = new List>();
var vals = sessionInfos.Children();
var metricsObj = sessionInfos["SessionMetrics"] as JArray;
@@ -408,8 +417,6 @@ namespace C4IT.DataHistoryProvider
var aggregatedValue = GetAggregationValue(valuesOfColumn, configColumn.AggregationType, colInfo.ValueType);
AddColumnData(retVal, colInfo.SourceName, ConvertToF4sdType(aggregatedValue, colInfo.ValueType));
}
-
-
}
catch (Exception E)
{
@@ -446,6 +453,179 @@ namespace C4IT.DataHistoryProvider
}
}
+ private async Task> GetSessionStateMetricsAsync(cF4sdConnectorIds UserIds, string TenantId, cF4sdWebRequestInfo RequestInfo, int MaxAge, int LogDeep, CancellationToken Token)
+ {
+
+ MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
+ if (cPerformanceLogger.IsActive && RequestInfo != null) { if (CM == null) CM = MethodBase.GetCurrentMethod(); cPerformanceLogger.LogPerformanceStart(LogDeep, CM, RequestInfo.id, RequestInfo.created); }
+ var _startTime = DateTime.UtcNow;
+
+ try
+ {
+
+ var strUrl = string.Format(constCitrixSessions, UserIds.citrixUserId.ToString());
+
+ if (!Collector.ClusterConfig.Tables.TryGetValue(constTableNameSessionStateMetrics, out var SessionTableDetails))
+ return null;
+
+ var citrixCommunication = await GetCitrixCommunicationForTenantAsync(TenantId, true);
+ if (citrixCommunication == null)
+ return null;
+
+ var res = await citrixCommunication.RequestAsync(strUrl, retryForbidden: false);
+ if (res != null)
+ {
+ JObject sessionInfos = res.Result;
+ var retVal = new cF4SDHealthCardRawData.cHealthCardTable()
+ {
+ Name = constTableNameSessionStateMetrics,
+ InformationClass = enumFasdInformationClass.VirtualSession,
+ IsStatic = true,
+ TableType = eDataHistoryTableType.Static
+ };
+
+ var dicVals = new List>();
+ var vals = sessionInfos.Children();
+ var metricsObj = sessionInfos["value"] as JArray;
+
+ if (metricsObj != null)
+ {
+ dicVals = metricsObj
+ .OfType()
+ .Where(o =>
+ o["StartDate"] != null &&
+ o["ConnectionState"] != null &&
+ DateTime.TryParse(o["StartDate"].ToString(), out _)
+ )
+ .GroupBy(o => new
+ {
+ Date = DateTime.Parse(o["StartDate"].ToString()).Date,
+ ConnectionState = (int)o["ConnectionState"]
+ })
+ .OrderBy(g => g.Key.Date)
+ .Select(g => new Dictionary
+ {
+ { "StartDate", g.Key.Date }, // ✅ DateTime
+ { "ConnectionState", g.Key.ConnectionState },
+ { "ConnectionCount", g.Count() }
+ })
+ .ToList();
+
+
+
+
+ const string startDateColumnName = "StartDate";
+ const string connectionStatusColumnName = "ConnectionState";
+
+ var groupedValues = dicVals
+ .Where(v =>
+ v.TryGetValue(startDateColumnName, out var collectDate) &&
+ collectDate is DateTime &&
+ v.TryGetValue(connectionStatusColumnName, out _))
+ .GroupBy(v => new
+ {
+ StartDate = ((DateTime)v[startDateColumnName]).Date,
+ ConnectionStatus = v[connectionStatusColumnName]
+ })
+ .Select(g => new Dictionary
+ {
+ { startDateColumnName, g.Key.StartDate },
+ { connectionStatusColumnName, g.Key.ConnectionStatus },
+ { "ConnectionCount", g.Count() }
+ })
+ .ToLookup(d => new
+ {
+ StartDate = (DateTime)d[startDateColumnName],
+ ConnectionStatus = d[connectionStatusColumnName],
+ ConnectionCount = d["ConnectionCount"]
+ });
+
+
+
+
+ for (int i = 0; i < MaxAge; i++)
+ {
+ DateTime referenceDate = DateTime.Now.AddDays(-i).Date;
+
+ //var valuesOfDay = groupedValues.FirstOrDefault(v => v.Key.Date == referenceDate);
+ var valuesOfDay = groupedValues.Where(g => g.Key.StartDate == referenceDate).SelectMany(g => g).ToList();
+
+ foreach (var colInfo in SessionTableDetails.Columns.Values)
+ {
+ try
+ {
+ if (valuesOfDay is null)
+ {
+ AddColumnData(retVal, colInfo.SourceName, ConvertToF4sdType(null, colInfo.ValueType));
+ continue;
+ }
+
+ var valuesOfColumn = valuesOfDay
+ .Select(v =>
+ {
+ if (v.TryGetValue(colInfo.SourceName, out var colValue))
+ return colValue;
+ else
+ return null;
+ })
+ .Where(v => v != null);
+
+ if (!valuesOfColumn.Any())
+ {
+ AddColumnData(retVal, colInfo.SourceName, ConvertToF4sdType(null, colInfo.ValueType));
+ continue;
+ }
+ if (colInfo is cDataHistoryConfigColumn configColumn && configColumn.AggregationType != eDataHistoryAggregationType.Unknown)
+ {
+ var aggregatedValue = GetAggregationValue(valuesOfColumn, configColumn.AggregationType, colInfo.ValueType);
+ AddColumnData(retVal, colInfo.SourceName, ConvertToF4sdType(aggregatedValue, colInfo.ValueType));
+ }
+ else
+ {
+ var value = valuesOfColumn.FirstOrDefault();
+ AddColumnData(retVal, colInfo.SourceName, ConvertToF4sdType(value, colInfo.ValueType));
+ }
+
+
+
+ }
+ catch (Exception E)
+ {
+ LogException(E);
+ }
+ }
+ }
+
+ return new List(1) { retVal };
+ }
+ else
+ {
+ LogEntry($"Could not get detailed sessionmetrics information from citrix with id {UserIds}. Sessionmetrics content is empty.", LogLevels.Warning);
+ }
+
+ }
+ }
+ catch (Exception E)
+ {
+ LogException(E);
+ }
+ finally
+ {
+ if (cPerformanceLogger.IsActive && RequestInfo != null) { cPerformanceLogger.LogPerformanceEnd(LogDeep, CM, RequestInfo.id, RequestInfo.created, _startTime); }
+ if (CM != null) LogMethodEnd(CM);
+ }
+
+ return null;
+
+ void AddColumnData(cF4SDHealthCardRawData.cHealthCardTable table, string columnName, object value)
+ {
+ if (table.Columns.TryGetValue(columnName, out var columnValues))
+ columnValues.Values.Add(value);
+ else
+ table.Columns.Add(columnName, new cF4SDHealthCardRawData.cHealthCardTableColumn(table) { ColumnName = columnName, Values = new List
+
diff --git a/F4SDwebService/Config/F4SD-HealthCard-Configuration.xml b/F4SDwebService/Config/F4SD-HealthCard-Configuration.xml
index 9ee101f..db0156b 100644
--- a/F4SDwebService/Config/F4SD-HealthCard-Configuration.xml
+++ b/F4SDwebService/Config/F4SD-HealthCard-Configuration.xml
@@ -1377,10 +1377,20 @@
Session
-
- Session Status
+
+ DNS Name
+
+
+ Domäne Name
+
+
+ Hosted Machine
+
+
+ Gerätname
+
@@ -1390,7 +1400,7 @@
-
+
@@ -1493,14 +1503,11 @@
-
-
-
Benutzer-Informationen
@@ -1521,11 +1528,7 @@
Desktopgruppe
-
-
- Session Id
-
Session-Informationen
@@ -1538,7 +1541,7 @@
Enddatum
-
+
Verbindungsstatus
@@ -1551,7 +1554,6 @@
Anonym
-
Verbindung-Informationen
@@ -1585,12 +1587,10 @@
Profilladezeit
-
Host-Informationen
-
Hostname
@@ -1613,12 +1613,28 @@
Wartungsmodus aktiv
-
+
+
+ Host Nutzung-Informationen
+
+
+ CPU Auslastung
+
+
+ RAM/Arbeitsspeicher Auslastung
+
+
+ Speicher Auslastung
+
+
+ Aktuelle Sitzungsanzahl
+
+
Host Nutzung-Informationen
-
+
CPU Auslastung
@@ -1632,15 +1648,12 @@
-
Netzwerk Performance
Information about network performance
Informationen über die Netzwerk Performance
-
-
Genutzte Input Bandbreite
Used Input Bandwidth in this Citrix session.
@@ -1656,7 +1669,6 @@
-
Verfügbare Output Bandbreite
Output Bandwidth available in this Citrix session.
@@ -1677,7 +1689,6 @@
-
Genutzte Output Bandbreite
Output Bandwidth used in this Citrix session.
@@ -1687,16 +1698,22 @@
+
-
HDX Performance
Information about HDX Performance
Informationen über HDX Performance
-
-
-
Input FPS
Frame rate per second transmitted from the server to the client.
@@ -1712,7 +1729,6 @@
-
Output FPS
The frame rate the client displays on the screen after processing.
@@ -1728,7 +1744,6 @@
-
FPS (Bilder pro Sekunde)
Measured FPS (Frame per second) in this Citrix session.
@@ -1749,14 +1764,11 @@
-
-
Session Latenz Performance
Information about session latencies
Informationen über die Session Latenz
-
ICA RTT
Measured response time (Round Trip Time) in this Citrix session.
@@ -1772,7 +1784,6 @@
-
ICA Latenz
Measured ICA Latency in this Citrix session.
@@ -1788,7 +1799,6 @@
-
Server Latenz
Measured Server Latency in this Citrix session.
@@ -1804,7 +1814,6 @@
-
Client Latenz
Measured Client Latency in this Citrix session.
@@ -1818,9 +1827,8 @@
Nutzung
-
+
-
WAN Latenz
Measured WAN Latency in this Citrix session.
@@ -1834,9 +1842,8 @@
Nutzung
-
+
-
DC (Delivery Controller) Latenz
Measured Delivery Controller Latency in this Citrix session.
@@ -1852,7 +1859,6 @@
-
diff --git a/F4SDwebService/Config/F4SD-Infrastructure-Configuration.xml b/F4SDwebService/Config/F4SD-Infrastructure-Configuration.xml
index 2447291..04e2d79 100644
--- a/F4SDwebService/Config/F4SD-Infrastructure-Configuration.xml
+++ b/F4SDwebService/Config/F4SD-Infrastructure-Configuration.xml
@@ -77,7 +77,7 @@
- onPremisesExtensionAttributes/extensionAttribute8 in ('C4IT', 'TS4U') and userType eq 'member' and accountEnabled eq true
+ onPremisesExtensionAttributes/extensionAttribute8 in ('C4IT', 'TS4U') and userType eq 'member' and accountEnabled eq true
diff --git a/F4SDwebService/Controllers/GetConfigurationController.cs b/F4SDwebService/Controllers/GetConfigurationController.cs
index 5492a4a..70e36a7 100644
--- a/F4SDwebService/Controllers/GetConfigurationController.cs
+++ b/F4SDwebService/Controllers/GetConfigurationController.cs
@@ -83,6 +83,38 @@ namespace FasdWebService.Controllers
return BadRequest();
}
+
+ [Route("api/GetCollectorStatus")]
+ public IHttpActionResult GetCollectorStatus()
+ {
+ MethodBase CM = null; if (cLogManager.DefaultLogger.IsDebug) { CM = MethodBase.GetCurrentMethod(); LogMethodBegin(CM); }
+
+ var requestInfo = new cF4sdWebRequestInfo("GetCollectorStatus", "configCockpit", cAuthentication.GetUserInfo(ActionContext));
+ if (cPerformanceLogger.IsActive && requestInfo != null) { cPerformanceLogger.LogPerformanceStart(0, requestInfo.requestName, requestInfo.id, requestInfo.created); }
+ var apiError = 0;
+
+ try
+ {
+ var retVal = WebApiApplication.Collector.GetCollectorStatus(requestInfo);
+ if (retVal != null)
+ return Ok(retVal);
+
+ apiError = (int)HttpStatusCode.BadRequest;
+ }
+ catch (Exception E)
+ {
+ apiError = E.HResult;
+ LogException(E);
+ }
+ finally
+ {
+ if (cPerformanceLogger.IsActive && requestInfo != null) { cPerformanceLogger.LogPerformanceEnd(0, requestInfo.requestName, requestInfo.id, requestInfo.created, requestInfo.created, ErrorCode: apiError); }
+ if (WebApiApplication.Debug_apiTiming) WebApiApplication.SaveApiTimingEntry(requestInfo.requestName, requestInfo.id, requestInfo.created, apiError);
+ if (CM != null) LogMethodEnd(CM);
+ }
+
+ return BadRequest();
+ }
}
}
\ No newline at end of file
diff --git a/F4SDwebService/Publish/Config/F4SD-CopyTemplate-Configuration.xml b/F4SDwebService/Publish/Config/F4SD-CopyTemplate-Configuration.xml
index 88f2e2e..99bf31c 100644
--- a/F4SDwebService/Publish/Config/F4SD-CopyTemplate-Configuration.xml
+++ b/F4SDwebService/Publish/Config/F4SD-CopyTemplate-Configuration.xml
@@ -1,44 +1,67 @@
-
-
- Ticket-Information
- Transfers the relevant information for ticket creation to the clipboard.
- Überträgt die relevanten Informationen für eine Ticket Erstellung in den Zwischenspeicher.
-
- %DeviceName.Label% %DeviceName.Value%
-%UserFullName.Label% %UserFullName.Value%
-%UserAccount.Label% %UserAccount.Value%
-%DeviceModel.Label% %DeviceModel.Value%
-%OsInfo.Label% %OsInfo.Value%
-%IpAddress.Label% %IpAddress.Value%
-%LastBoot.Label% %LastBoot.Value%
-%LastSeen.Label% %LastSeen.Value%
- <table border="1" cellpadding="5,1,5,1"><tbody>
-<tr><td><em>%DeviceName.Label%</em></td><td style="color: #0000ff;">%DeviceName.Value%</td></tr>
-<tr><td><em>%UserFullName.Label%</em></td><td>%UserFullName.Value%</td></tr>
-<tr><td><em>%UserAccount.Label%</em></td><td>%UserAccount.Value%</td></tr>
-<tr><td><em>%OsInfo.Label%</em></td><td>%OsInfo.Value%</td></tr>
-<tr><td><em>%IpAddress.Label%</em></td><td>%IpAddress.Value%</td></tr>
-<tr><td><em>%LastBoot.Label%</em></td><td>%LastBoot.Value%</td></tr>
-<tr><td><em>%LastSeen.Label%</em></td><td>%LastSeen.Value%</td></tr>
-</tbody></table>
+
+
+ Ticket-Information-Computer
+ Transfers the relevant information for ticket creation to the clipboard.
+ Überträgt die relevanten Informationen für eine Ticket Erstellung in den Zwischenspeicher.
+
+
+ %DeviceName.Label% %DeviceName.Value%
+ %UserFullName.Label% %UserFullName.Value%
+ %UserAccount.Label% %UserAccount.Value%
+ %DeviceModel.Label% %DeviceModel.Value%
+ %OsInfo.Label% %OsInfo.Value%
+ %IpAddress.Label% %IpAddress.Value%
+ %LastBoot.Label% %LastBoot.Value%
+ %LastSeen.Label% %LastSeen.Value%
+
+
+ <table border="1" cellpadding="5,1,5,1"><tbody>
+ <tr><td><em>%DeviceName.Label%</em></td><td style="color: #0000ff;">%DeviceName.Value%</td></tr>
+ <tr><td><em>%UserFullName.Label%</em></td><td>%UserFullName.Value%</td></tr>
+ <tr><td><em>%UserAccount.Label%</em></td><td>%UserAccount.Value%</td></tr>
+ <tr><td><em>%OsInfo.Label%</em></td><td>%OsInfo.Value%</td></tr>
+ <tr><td><em>%IpAddress.Label%</em></td><td>%IpAddress.Value%</td></tr>
+ <tr><td><em>%LastBoot.Label%</em></td><td>%LastBoot.Value%</td></tr>
+ <tr><td><em>%LastSeen.Label%</em></td><td>%LastSeen.Value%</td></tr>
+ </tbody></table>
+
+
+
+ Ticket Information VM
+ Transfers the relevant information for ticket creation to the clipboard.
+ Überträgt die relevanten Informationen für eine Ticket Erstellung in den Zwischenspeicher.
+
+
+ %VirtualSessionName.Label% %VirtualSessionName.Value%
+ %VirtualSessionStatus.Label% %VirtualSessionStatus.Value%
+ %HostedMachine.Label% %HostedMachine.Value%
+ %DeviceName.Label% %DeviceName.Value%
+
+
+ <table border="1" cellpadding="5,1,5,1"><tbody>
+ <tr><td><em>%VirtualSessionName.Label%</em></td><td style="color: #0000ff;">%VirtualSessionName.Value%</td></tr>
+ <tr><td><em>%VirtualSessionStatus.Label%</em></td><td>%VirtualSessionStatus.Value%</td></tr>
+ <tr><td><em>%HostedMachine.Label%</em></td><td>%HostedMachine.Value%</td></tr>
+ </tbody></table>
+
Computer Name
-
+
- %DeviceName.Value%
+ %DeviceName.Label% %DeviceName.Value%
Anwendername
- %UserFullName.Value%
+ %UserFullName.Label% %UserFullName.Value%
Anwender Account
- %UserAccount.Value%
+ %UserAccount.Label% %UserAccount.Value%
\ No newline at end of file
diff --git a/F4SDwebService/Publish/Config/F4SD-DataClusters-Configuration.xml b/F4SDwebService/Publish/Config/F4SD-DataClusters-Configuration.xml
index f989495..8223146 100644
--- a/F4SDwebService/Publish/Config/F4SD-DataClusters-Configuration.xml
+++ b/F4SDwebService/Publish/Config/F4SD-DataClusters-Configuration.xml
@@ -1378,6 +1378,14 @@
+
diff --git a/F4SDwebService/Publish/Config/F4SD-HealthCard-Configuration.xml b/F4SDwebService/Publish/Config/F4SD-HealthCard-Configuration.xml
index 9ee101f..db0156b 100644
--- a/F4SDwebService/Publish/Config/F4SD-HealthCard-Configuration.xml
+++ b/F4SDwebService/Publish/Config/F4SD-HealthCard-Configuration.xml
@@ -1377,10 +1377,20 @@
Session
-
- Session Status
+
+ DNS Name
+
+
+ Domäne Name
+
+
+ Hosted Machine
+
+
+ Gerätname
+
@@ -1390,7 +1400,7 @@
-
+
@@ -1493,14 +1503,11 @@
-
-
-
Benutzer-Informationen
@@ -1521,11 +1528,7 @@
Desktopgruppe
-
-
- Session Id
-
Session-Informationen
@@ -1538,7 +1541,7 @@
Enddatum
-
+
Verbindungsstatus
@@ -1551,7 +1554,6 @@
Anonym
-
Verbindung-Informationen
@@ -1585,12 +1587,10 @@
Profilladezeit
-
Host-Informationen
-
Hostname
@@ -1613,12 +1613,28 @@
Wartungsmodus aktiv
-
+
+
+ Host Nutzung-Informationen
+
+
+ CPU Auslastung
+
+
+ RAM/Arbeitsspeicher Auslastung
+
+
+ Speicher Auslastung
+
+
+ Aktuelle Sitzungsanzahl
+
+
Host Nutzung-Informationen
-
+
CPU Auslastung
@@ -1632,15 +1648,12 @@
-
Netzwerk Performance
Information about network performance
Informationen über die Netzwerk Performance
-
-
Genutzte Input Bandbreite
Used Input Bandwidth in this Citrix session.
@@ -1656,7 +1669,6 @@
-
Verfügbare Output Bandbreite
Output Bandwidth available in this Citrix session.
@@ -1677,7 +1689,6 @@
-
Genutzte Output Bandbreite
Output Bandwidth used in this Citrix session.
@@ -1687,16 +1698,22 @@
+
-
HDX Performance
Information about HDX Performance
Informationen über HDX Performance
-
-
-
Input FPS
Frame rate per second transmitted from the server to the client.
@@ -1712,7 +1729,6 @@
-
Output FPS
The frame rate the client displays on the screen after processing.
@@ -1728,7 +1744,6 @@
-
FPS (Bilder pro Sekunde)
Measured FPS (Frame per second) in this Citrix session.
@@ -1749,14 +1764,11 @@
-
-
Session Latenz Performance
Information about session latencies
Informationen über die Session Latenz
-
ICA RTT
Measured response time (Round Trip Time) in this Citrix session.
@@ -1772,7 +1784,6 @@
-
ICA Latenz
Measured ICA Latency in this Citrix session.
@@ -1788,7 +1799,6 @@
-
Server Latenz
Measured Server Latency in this Citrix session.
@@ -1804,7 +1814,6 @@
-
Client Latenz
Measured Client Latency in this Citrix session.
@@ -1818,9 +1827,8 @@
Nutzung
-
+
-
WAN Latenz
Measured WAN Latency in this Citrix session.
@@ -1834,9 +1842,8 @@
Nutzung
-
+
-
DC (Delivery Controller) Latenz
Measured Delivery Controller Latency in this Citrix session.
@@ -1852,7 +1859,6 @@
-
diff --git a/F4SDwebService/Publish/Config/F4SD-Infrastructure-Configuration.xml b/F4SDwebService/Publish/Config/F4SD-Infrastructure-Configuration.xml
index 2447291..04e2d79 100644
--- a/F4SDwebService/Publish/Config/F4SD-Infrastructure-Configuration.xml
+++ b/F4SDwebService/Publish/Config/F4SD-Infrastructure-Configuration.xml
@@ -77,7 +77,7 @@
- onPremisesExtensionAttributes/extensionAttribute8 in ('C4IT', 'TS4U') and userType eq 'member' and accountEnabled eq true
+ onPremisesExtensionAttributes/extensionAttribute8 in ('C4IT', 'TS4U') and userType eq 'member' and accountEnabled eq true
diff --git a/F4SDwebService/Publish/Config/F4SD-Infrastructure-Configuration.xsd b/F4SDwebService/Publish/Config/F4SD-Infrastructure-Configuration.xsd
index ce9c2fc..3387100 100644
--- a/F4SDwebService/Publish/Config/F4SD-Infrastructure-Configuration.xsd
+++ b/F4SDwebService/Publish/Config/F4SD-Infrastructure-Configuration.xsd
@@ -1,47 +1,47 @@
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
@@ -75,117 +75,117 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -210,137 +210,137 @@
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -352,203 +352,211 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
@@ -569,7 +577,7 @@
-
+
@@ -616,25 +624,25 @@
-
+
-
-
+
+
-
-
-
-
-
+
+
+
+
+