├── doc
├── log.png
├── finish.png
└── service.png
├── sample
├── Linux
│ ├── writeflag
│ ├── rawkvp
│ ├── kvpio.py
│ └── showkvp
└── Windows
│ └── showkvp.ps1
├── LICENSE.md
├── src
├── Service
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ ├── app.config
│ ├── Program.cs
│ ├── EnhacedMonitoringProvider.Designer.cs
│ ├── EnhacedMonitoringProvider.cs
│ ├── Service.csproj
│ └── EnhacedMonitoringProvider.resx
├── EnhancedMonitoring
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ ├── Logging
│ │ ├── LogWriter.cs
│ │ ├── LogLevel.cs
│ │ ├── EventLogWriter.cs
│ │ ├── FileLogWriter.cs
│ │ └── Logger.cs
│ ├── Configuration
│ │ ├── MgmtObjectType.cs
│ │ ├── MgmtObjectReturnValueType.cs
│ │ ├── WhereArgConfiguration.cs
│ │ ├── KvpConfiguration.cs
│ │ ├── PerfCounterConfiguration.cs
│ │ ├── SupportedVMDetectorConfiguration.cs
│ │ ├── MgmtObjectConfiguration.cs
│ │ └── MonitorConfiguration.cs
│ ├── WMIQueryHelper.cs
│ ├── DataFormat
│ │ ├── XmlDataFormatter.cs
│ │ └── DataFormatHelper.cs
│ ├── DataCollector
│ │ ├── MgmtObject.cs
│ │ ├── DynamicMemoryMgmtObject.cs
│ │ └── QueryMgmtObject.cs
│ ├── NamedArgumentHelper.cs
│ ├── SupportedVMDetector.cs
│ ├── EnhancedMonitoring.csproj
│ ├── KeyValuePairWriter.cs
│ └── MonitoringTask.cs
├── UnitTest
│ ├── MonitorTaskTest.cs
│ ├── TestToXmlExpectedOutput.xml
│ ├── Properties
│ │ └── AssemblyInfo.cs
│ ├── WMIQueryHelperTest.cs
│ ├── SupportedVMDetectorTest.cs
│ ├── DynamicMemoryMgmtObjectTest.cs
│ ├── MonitorConfigurationTest.cs
│ ├── DataPackingHelperTest.cs
│ ├── SampleResult.xml
│ ├── EventLogTest.cs
│ ├── LoggerTest.cs
│ ├── JSONHelper.cs
│ ├── NamedArgumentHelperTest.cs
│ ├── SampleMonitor.xml
│ ├── FormatHelperTest.cs
│ ├── KVPWriterTest.cs
│ ├── MetricTest.cs
│ ├── TestFileLogWriter.cs
│ └── UnitTest.csproj
└── EnhancedMonitoring.sln
├── SECURITY.md
├── .gitignore
├── packages
└── MSI
│ └── EnhancedMonitoring
│ ├── Setup.wixproj
│ └── Product.wxs
└── README.md
/doc/log.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/enhanced-monitoring-service/HEAD/doc/log.png
--------------------------------------------------------------------------------
/doc/finish.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/enhanced-monitoring-service/HEAD/doc/finish.png
--------------------------------------------------------------------------------
/doc/service.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/microsoft/enhanced-monitoring-service/HEAD/doc/service.png
--------------------------------------------------------------------------------
/sample/Linux/writeflag:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | #
3 | #Read kvp and display on screen
4 | #
5 |
6 | import io
7 | import kvpio
8 |
9 | if __name__ == "__main__":
10 | kvp = [0] * (512 + 2048)
11 | key = bytes("Enhanced_Monitoring_Supported")
12 | val = bytes("1")
13 | kvp[0: len(key)] = key[0 : len(key)]
14 | kvp[512 : 512 + len(val)] = val[0 : len(val)]
15 | b = bytearray(kvp)
16 | kvpio.write_bytes(1, b)
17 |
--------------------------------------------------------------------------------
/sample/Linux/rawkvp:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | #
3 | #Read kvp and display on screen
4 | #
5 |
6 | import io
7 | import sys
8 | import kvpio
9 |
10 | if __name__ == '__main__':
11 | print_key = len(sys.argv) > 1 and sys.argv[1].lower() == 'key'
12 | for i in [0, 1, 2, 3, 4]:
13 | print "---------------------------------------------------------------------"
14 | print "Pool " + str(i) + ":"
15 | print "---------------------------------------------------------------------"
16 | data = kvpio.read_raw_kvp(i)
17 | for k in data:
18 | if not print_key:
19 | print str(k) + "=" + str(data[k])
20 | else:
21 | print str(k)
22 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2015 Microsoft
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/src/Service/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | //The MIT License (MIT)
2 | //
3 | //Copyright 2015 Microsoft Corporation
4 | //
5 | //Permission is hereby granted, free of charge, to any person obtaining a copy
6 | //of this software and associated documentation files (the "Software"), to deal
7 | //in the Software without restriction, including without limitation the rights
8 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | //copies of the Software, and to permit persons to whom the Software is
10 | //furnished to do so, subject to the following conditions:
11 | //
12 | //The above copyright notice and this permission notice shall be included in
13 | //all copies or substantial portions of the Software.
14 | //
15 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | //THE SOFTWARE.
22 | //
23 |
--------------------------------------------------------------------------------
/src/EnhancedMonitoring/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | //The MIT License (MIT)
2 | //
3 | //Copyright 2015 Microsoft Corporation
4 | //
5 | //Permission is hereby granted, free of charge, to any person obtaining a copy
6 | //of this software and associated documentation files (the "Software"), to deal
7 | //in the Software without restriction, including without limitation the rights
8 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | //copies of the Software, and to permit persons to whom the Software is
10 | //furnished to do so, subject to the following conditions:
11 | //
12 | //The above copyright notice and this permission notice shall be included in
13 | //all copies or substantial portions of the Software.
14 | //
15 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | //THE SOFTWARE.
22 | //
23 |
24 |
--------------------------------------------------------------------------------
/src/Service/app.config:
--------------------------------------------------------------------------------
1 |
2 |
3 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/src/EnhancedMonitoring/Logging/LogWriter.cs:
--------------------------------------------------------------------------------
1 | //The MIT License (MIT)
2 | //
3 | //Copyright 2015 Microsoft Corporation
4 | //
5 | //Permission is hereby granted, free of charge, to any person obtaining a copy
6 | //of this software and associated documentation files (the "Software"), to deal
7 | //in the Software without restriction, including without limitation the rights
8 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | //copies of the Software, and to permit persons to whom the Software is
10 | //furnished to do so, subject to the following conditions:
11 | //
12 | //The above copyright notice and this permission notice shall be included in
13 | //all copies or substantial portions of the Software.
14 | //
15 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | //THE SOFTWARE.
22 | //
23 | using System;
24 | using System.Collections.Generic;
25 | using System.Linq;
26 | using System.Text;
27 | using System.Threading.Tasks;
28 |
29 | namespace EnhancedMonitoring.Logging
30 | {
31 | public interface LogWriter
32 | {
33 | void Write(LogLevel level, String msg);
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/sample/Linux/kvpio.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | #
3 | #Read kvp and display on screen
4 | #
5 |
6 | import io
7 |
8 | def read_bytes(pool):
9 | filepath = "/var/lib/hyperv/.kvp_pool_" + str(pool)
10 | mode = 'r'
11 | c = None
12 | try:
13 | with open(filepath, mode) as F:
14 | c=F.read()
15 | F.close()
16 | except IOError, e:
17 | print e
18 | b = bytes(c)
19 | return b
20 |
21 | def bytes_to_str(b, start, end):
22 | buf = None
23 | for i in range(start, end):
24 | if ord(b[i]) == 0:#Found string end
25 | buf = bytearray(i - start)
26 | buf[:] = b[start : i]
27 | break
28 | if(buf):
29 | return buf.decode('utf-8')
30 | else:
31 | return None
32 |
33 | def read_raw_kvp(pool):
34 | b = read_bytes(pool)
35 | key_start = 0
36 | val_start = 512
37 | key_len = 512
38 | val_len = 2048
39 | step = key_len + val_len
40 | data={}
41 | while val_start < len(b):
42 | key = bytes_to_str(b, key_start, key_start + key_len)
43 | val = bytes_to_str(b, val_start, val_start + val_len)
44 | data[key] = val
45 | key_start += step
46 | val_start += step
47 | return data;
48 |
49 | def write_bytes(pool, b):
50 | filepath = "/var/lib/hyperv/.kvp_pool_" + str(pool)
51 | mode = 'wb'
52 | c = None
53 | try:
54 | with open(filepath, mode) as F:
55 | c=F.write(b)
56 | F.close()
57 | except IOError, e:
58 | print e
59 |
--------------------------------------------------------------------------------
/src/EnhancedMonitoring/Configuration/MgmtObjectType.cs:
--------------------------------------------------------------------------------
1 | //The MIT License (MIT)
2 | //
3 | //Copyright 2015 Microsoft Corporation
4 | //
5 | //Permission is hereby granted, free of charge, to any person obtaining a copy
6 | //of this software and associated documentation files (the "Software"), to deal
7 | //in the Software without restriction, including without limitation the rights
8 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | //copies of the Software, and to permit persons to whom the Software is
10 | //furnished to do so, subject to the following conditions:
11 | //
12 | //The above copyright notice and this permission notice shall be included in
13 | //all copies or substantial portions of the Software.
14 | //
15 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | //THE SOFTWARE.
22 | //
23 | using System;
24 | using System.Collections.Generic;
25 | using System.Linq;
26 | using System.Text;
27 | using System.Threading.Tasks;
28 |
29 | namespace EnhancedMonitoring.Configuration
30 | {
31 | public enum MgmtObjectType
32 | {
33 | Query = 0,
34 | DynamicMemory = 1,
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/EnhancedMonitoring/Configuration/MgmtObjectReturnValueType.cs:
--------------------------------------------------------------------------------
1 | //The MIT License (MIT)
2 | //
3 | //Copyright 2015 Microsoft Corporation
4 | //
5 | //Permission is hereby granted, free of charge, to any person obtaining a copy
6 | //of this software and associated documentation files (the "Software"), to deal
7 | //in the Software without restriction, including without limitation the rights
8 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | //copies of the Software, and to permit persons to whom the Software is
10 | //furnished to do so, subject to the following conditions:
11 | //
12 | //The above copyright notice and this permission notice shall be included in
13 | //all copies or substantial portions of the Software.
14 | //
15 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | //THE SOFTWARE.
22 | //
23 | using System;
24 | using System.Collections.Generic;
25 | using System.Linq;
26 | using System.Text;
27 | using System.Threading.Tasks;
28 |
29 | namespace EnhancedMonitoring.Configuration
30 | {
31 | public enum MgmtObjectReturnValueType
32 | {
33 | Multiple = 0,
34 | Single
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/src/EnhancedMonitoring/Logging/LogLevel.cs:
--------------------------------------------------------------------------------
1 | //The MIT License (MIT)
2 | //
3 | //Copyright 2015 Microsoft Corporation
4 | //
5 | //Permission is hereby granted, free of charge, to any person obtaining a copy
6 | //of this software and associated documentation files (the "Software"), to deal
7 | //in the Software without restriction, including without limitation the rights
8 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | //copies of the Software, and to permit persons to whom the Software is
10 | //furnished to do so, subject to the following conditions:
11 | //
12 | //The above copyright notice and this permission notice shall be included in
13 | //all copies or substantial portions of the Software.
14 | //
15 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | //THE SOFTWARE.
22 | //
23 | using System;
24 | using System.Collections.Generic;
25 | using System.Linq;
26 | using System.Text;
27 | using System.Threading.Tasks;
28 |
29 | namespace EnhancedMonitoring.Logging
30 | {
31 | public enum LogLevel
32 | {
33 | Verbose = -1,
34 | Info = 0,
35 | Warning = 1,
36 | Error = 2
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/sample/Linux/showkvp:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | #
3 | #Read perf counters
4 | #
5 |
6 | import datetime
7 | import time
8 | import json
9 | import sys
10 | import base64
11 | from StringIO import StringIO
12 | import kvpio
13 | import xml.etree.ElementTree as ET
14 |
15 | def parseXML(s):
16 | xmldoc = ET.fromstring(s)
17 | return xmldoc
18 |
19 | def readDataPart(data, i):
20 | val = data.get('Enhanced_Monitoring_Metric_Data_Item_Part_' + str(i), None)
21 | return parseXML(val)
22 |
23 | def readPerfCounter():
24 | data = kvpio.read_raw_kvp(0)
25 | dataStr = ""
26 |
27 | part_0 = readDataPart(data, 0)
28 | if not part_0:
29 | print "Data not found"
30 | return;
31 | ts = part_0.find('ts').text
32 | dataStr += part_0.find('data').text
33 | for i in range(1, int(part_0.find('all').text)):
34 | part_i = readDataPart(data, i)
35 | if ts != part_i.find('ts').text:
36 | print "Wrong timestamp:" + str(ts) + ", Part:" + str(i)
37 | dataStr += part_i.find('data').text
38 |
39 | dataStr = base64.b64decode(dataStr)
40 |
41 | print "------------------------------------------------------------------------"
42 | ts = float(ts)
43 | timestamp = datetime.datetime.fromtimestamp(ts/1000).strftime('%Y-%m-%d %H:%M:%S %z')
44 | print dataStr
45 | print timestamp
46 |
47 | if __name__ == "__main__":
48 | args = sys.argv[1:]
49 | loop = False
50 |
51 | if len(args) > 0 and args[0].lower() == 'loop':
52 | loop = True
53 |
54 | readPerfCounter()
55 | while loop:
56 | time.sleep(60)
57 | readPerfCounter()
58 |
--------------------------------------------------------------------------------
/src/EnhancedMonitoring/Configuration/WhereArgConfiguration.cs:
--------------------------------------------------------------------------------
1 | //The MIT License (MIT)
2 | //
3 | //Copyright 2015 Microsoft Corporation
4 | //
5 | //Permission is hereby granted, free of charge, to any person obtaining a copy
6 | //of this software and associated documentation files (the "Software"), to deal
7 | //in the Software without restriction, including without limitation the rights
8 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | //copies of the Software, and to permit persons to whom the Software is
10 | //furnished to do so, subject to the following conditions:
11 | //
12 | //The above copyright notice and this permission notice shall be included in
13 | //all copies or substantial portions of the Software.
14 | //
15 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | //THE SOFTWARE.
22 | //
23 | using System;
24 | using System.Collections.Generic;
25 | using System.Linq;
26 | using System.Text;
27 | using System.Threading.Tasks;
28 | using System.Xml.Serialization;
29 |
30 | namespace EnhancedMonitoring.Configuration
31 | {
32 |
33 | [XmlRoot("Monitor")]
34 | public class WhereArgConfiguration
35 | {
36 |
37 | [XmlAttribute("Escape")]
38 | public Boolean Escape { get; set; }
39 |
40 | [XmlText]
41 | public String Name { get; set; }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/EnhancedMonitoring/Configuration/KvpConfiguration.cs:
--------------------------------------------------------------------------------
1 | //The MIT License (MIT)
2 | //
3 | //Copyright 2015 Microsoft Corporation
4 | //
5 | //Permission is hereby granted, free of charge, to any person obtaining a copy
6 | //of this software and associated documentation files (the "Software"), to deal
7 | //in the Software without restriction, including without limitation the rights
8 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | //copies of the Software, and to permit persons to whom the Software is
10 | //furnished to do so, subject to the following conditions:
11 | //
12 | //The above copyright notice and this permission notice shall be included in
13 | //all copies or substantial portions of the Software.
14 | //
15 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | //THE SOFTWARE.
22 | //
23 | using System;
24 | using System.Collections.Generic;
25 | using System.Linq;
26 | using System.Text;
27 | using System.Threading.Tasks;
28 | using System.Xml.Serialization;
29 |
30 | namespace EnhancedMonitoring.Configuration
31 | {
32 | [XmlRoot("Kvp")]
33 | public class KvpConfiguration
34 | {
35 | [XmlElement("BatchMode")]
36 | public Boolean BatchMode { get; set; }
37 |
38 | [XmlElement("WriteInterval")]
39 | public Int32 WriteInterval { get; set; }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/src/EnhancedMonitoring/Configuration/PerfCounterConfiguration.cs:
--------------------------------------------------------------------------------
1 | //The MIT License (MIT)
2 | //
3 | //Copyright 2015 Microsoft Corporation
4 | //
5 | //Permission is hereby granted, free of charge, to any person obtaining a copy
6 | //of this software and associated documentation files (the "Software"), to deal
7 | //in the Software without restriction, including without limitation the rights
8 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | //copies of the Software, and to permit persons to whom the Software is
10 | //furnished to do so, subject to the following conditions:
11 | //
12 | //The above copyright notice and this permission notice shall be included in
13 | //all copies or substantial portions of the Software.
14 | //
15 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | //THE SOFTWARE.
22 | //
23 | using System;
24 | using System.Collections.Generic;
25 | using System.Linq;
26 | using System.Text;
27 | using System.Threading.Tasks;
28 | using System.Xml.Serialization;
29 |
30 | namespace EnhancedMonitoring.Configuration
31 | {
32 | [XmlRoot("Monitor")]
33 | public class PerfCounterConfiguration
34 | {
35 | [XmlElement("As")]
36 | public String As { get; set; }
37 |
38 | [XmlElement("Select")]
39 | public String Select { get; set; }
40 |
41 | }
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/src/Service/Program.cs:
--------------------------------------------------------------------------------
1 | //The MIT License (MIT)
2 | //
3 | //Copyright 2015 Microsoft Corporation
4 | //
5 | //Permission is hereby granted, free of charge, to any person obtaining a copy
6 | //of this software and associated documentation files (the "Software"), to deal
7 | //in the Software without restriction, including without limitation the rights
8 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | //copies of the Software, and to permit persons to whom the Software is
10 | //furnished to do so, subject to the following conditions:
11 | //
12 | //The above copyright notice and this permission notice shall be included in
13 | //all copies or substantial portions of the Software.
14 | //
15 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | //THE SOFTWARE.
22 | //
23 | using System;
24 | using System.Collections.Generic;
25 | using System.Linq;
26 | using System.ServiceProcess;
27 | using System.Text;
28 | using System.Threading.Tasks;
29 |
30 | namespace EnhancedMonitoring.Service
31 | {
32 | static class Program
33 | {
34 | ///
35 | /// The main entry point for the application.
36 | ///
37 | static void Main()
38 | {
39 |
40 | ServiceBase[] ServicesToRun;
41 | ServicesToRun = new ServiceBase[]
42 | {
43 | new EnhacedMonitoring()
44 | };
45 | ServiceBase.Run(ServicesToRun);
46 | }
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/src/EnhancedMonitoring/WMIQueryHelper.cs:
--------------------------------------------------------------------------------
1 | //The MIT License (MIT)
2 | //
3 | //Copyright 2015 Microsoft Corporation
4 | //
5 | //Permission is hereby granted, free of charge, to any person obtaining a copy
6 | //of this software and associated documentation files (the "Software"), to deal
7 | //in the Software without restriction, including without limitation the rights
8 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | //copies of the Software, and to permit persons to whom the Software is
10 | //furnished to do so, subject to the following conditions:
11 | //
12 | //The above copyright notice and this permission notice shall be included in
13 | //all copies or substantial portions of the Software.
14 | //
15 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | //THE SOFTWARE.
22 | //
23 | using System;
24 | using System.Collections.Generic;
25 | using System.Linq;
26 | using System.Text;
27 | using System.Threading.Tasks;
28 |
29 | namespace EnhancedMonitoring
30 | {
31 | public class WMIQueryHelper
32 | {
33 | public static String EscapeLikeCondition(String condition)
34 | {
35 | if (!String.IsNullOrEmpty(condition))
36 | {
37 | //Need to escape "[", "%", "_"
38 | condition = condition.Replace("[", "[[]");
39 | condition = condition.Replace("%", "[%]");
40 | condition = condition.Replace("_", "[_]");
41 |
42 | //No need to escape "]", "^"
43 | }
44 | return condition;
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/sample/Windows/showkvp.ps1:
--------------------------------------------------------------------------------
1 |
2 | param(
3 | [Parameter(Mandatory=$false)]
4 | [Switch]$loop=$true,
5 | )
6 |
7 |
8 | Function Show-KVP
9 | {
10 |
11 | $path = 'HKLM:\SOFTWARE\Microsoft\Virtual Machine\External'
12 | $kvp = Get-Item -Path $path;
13 | if($kvp -eq $null)
14 | {
15 | Write-Error "Registry key not found:$path";
16 | exit(-1);
17 | }
18 | $part_0 = $kvp.GetValue("Enhanced_Monitoring_Metric_Data_Item_Part_0");
19 |
20 | if($part_0 -eq $null)
21 | {
22 | Write-Error "Performance data not found";
23 | exit(-1);
24 | }
25 | $data_0 = $part_0 | ConvertFrom-Xml
26 | if($data_0 -eq $null)
27 | {
28 | Write-Error "Convert to Xml failed:$part_0";
29 | exit(-1);
30 | }
31 |
32 | $dataStr = $data_0.data;
33 | $UtcTime = Get-Date -Date "1970-01-01 00:00:00Z"
34 | $timestamp = $UtcTime.AddMilliseconds($data_0.ts);
35 |
36 | for($i = 1; $i -lt $data_0.all; $i++)
37 | {
38 | $part_i = $kvp.GetValue("Enhanced_Monitoring_Metric_Data_Item_Part_" + $i);
39 | $data_i = $part_i | ConvertFrom-Xml
40 | if($data_i -eq $null)
41 | {
42 | Write-Error "Convert to xml failed:$part_i";
43 | exit(-1);
44 | }
45 |
46 | $dataStr += $data_i.data
47 | }
48 |
49 | $dataStr = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($dataStr))
50 |
51 | $data = ConvertFrom-Xml $dataStr
52 |
53 | if($selector -ne $null -and $selector -ne '')
54 | {
55 | $data = $data | Select -ExpandProperty $selector
56 | }
57 |
58 | Write-Host "-------------------------------------------------------------------------------------------";
59 | Write-Host $data
60 | Write-Host $timestamp.ToString("yyyy/MM/dd HH:mm:ss zzz")
61 | }
62 |
63 |
64 | Show-KVP
65 | while($loop -eq $true)
66 | {
67 | Write-Host "Waiting..." -nonewline
68 | for($i=60; $i -gt 0; $i--)
69 | {
70 | Write-Host "`rWaiting $i..." -nonewline
71 | Start-Sleep -s 1
72 | }
73 | Write-Host "`r" -nonewline
74 | Show-KVP
75 | }
--------------------------------------------------------------------------------
/src/UnitTest/MonitorTaskTest.cs:
--------------------------------------------------------------------------------
1 | //The MIT License (MIT)
2 | //
3 | //Copyright 2015 Microsoft Corporation
4 | //
5 | //Permission is hereby granted, free of charge, to any person obtaining a copy
6 | //of this software and associated documentation files (the "Software"), to deal
7 | //in the Software without restriction, including without limitation the rights
8 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | //copies of the Software, and to permit persons to whom the Software is
10 | //furnished to do so, subject to the following conditions:
11 | //
12 | //The above copyright notice and this permission notice shall be included in
13 | //all copies or substantial portions of the Software.
14 | //
15 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | //THE SOFTWARE.
22 | //
23 | using System;
24 | using Microsoft.VisualStudio.TestTools.UnitTesting;
25 | using EnhancedMonitoring.Configuration;
26 | using EnhancedMonitoring;
27 | using EnhancedMonitoring.Logging;
28 |
29 | namespace UnitTest
30 | {
31 | [TestClass]
32 | public class MonitorTaskTest
33 | {
34 | [TestMethod]
35 | public void TestMonitorTask()
36 | {
37 | var watcher = System.Diagnostics.Stopwatch.StartNew();
38 | MonitorConfiguration conf = MonitorConfiguration.Load(@"..\..\..\EnhancedMonitoring\Configuration\EnhancedMonitoringProviderConfig.xml");
39 | conf.LogFilePath = @"C:\ProgramData\Enhanced Monitoring\log\monitor.log";
40 | conf.LogLevel = "Verbose";
41 | Logger.Init(conf);
42 | MonitoringTask task = MonitoringTask.CreateInstance(conf as MonitorConfiguration);
43 | task.Run();
44 | Console.WriteLine(String.Format("Elapsed: {0}ms", watcher.ElapsedMilliseconds));
45 | }
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/EnhancedMonitoring/Configuration/SupportedVMDetectorConfiguration.cs:
--------------------------------------------------------------------------------
1 | //The MIT License (MIT)
2 | //
3 | //Copyright 2015 Microsoft Corporation
4 | //
5 | //Permission is hereby granted, free of charge, to any person obtaining a copy
6 | //of this software and associated documentation files (the "Software"), to deal
7 | //in the Software without restriction, including without limitation the rights
8 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | //copies of the Software, and to permit persons to whom the Software is
10 | //furnished to do so, subject to the following conditions:
11 | //
12 | //The above copyright notice and this permission notice shall be included in
13 | //all copies or substantial portions of the Software.
14 | //
15 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | //THE SOFTWARE.
22 | //
23 | using System;
24 | using System.Collections.Generic;
25 | using System.Linq;
26 | using System.Text;
27 | using System.Threading.Tasks;
28 | using System.Xml.Serialization;
29 |
30 | namespace EnhancedMonitoring.Configuration
31 | {
32 | [XmlRoot("SupportedVMDetector")]
33 | public class SupportedVMDetectorConfiguration
34 | {
35 | [XmlElement("GuestDataItemKey")]
36 | public String GuestDataItemKey { get; set; }
37 |
38 | [XmlArray("VirtualMachineProperties")]
39 | [XmlArrayItem("VirtualMachineProperties")]
40 | public VirtualMachineProperties VirtualMachineProperties { get; set; }
41 | }
42 |
43 | public class VirtualMachineProperties : List
44 | {
45 |
46 | }
47 |
48 | [XmlRoot("VirtualMachineProperty")]
49 | public class VirtualMachineProperty
50 | {
51 | [XmlElement("Select")]
52 | public String Select { get; set; }
53 |
54 | [XmlElement("As")]
55 | public String As { get; set; }
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/src/EnhancedMonitoring/DataFormat/XmlDataFormatter.cs:
--------------------------------------------------------------------------------
1 | //The MIT License (MIT)
2 | //
3 | //Copyright 2015 Microsoft Corporation
4 | //
5 | //Permission is hereby granted, free of charge, to any person obtaining a copy
6 | //of this software and associated documentation files (the "Software"), to deal
7 | //in the Software without restriction, including without limitation the rights
8 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | //copies of the Software, and to permit persons to whom the Software is
10 | //furnished to do so, subject to the following conditions:
11 | //
12 | //The above copyright notice and this permission notice shall be included in
13 | //all copies or substantial portions of the Software.
14 | //
15 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | //THE SOFTWARE.
22 | //
23 | using System;
24 | using System.Collections.Generic;
25 | using System.Linq;
26 | using System.Text;
27 | using System.Threading.Tasks;
28 |
29 | namespace EnhancedMonitoring.DataFormat
30 | {
31 | public class XmlDataFormatter
32 | {
33 | protected const Int32 DEFAULT_VALUE_LENGTH = 800;
34 |
35 | private Configuration.MonitorConfiguration conf;
36 |
37 | public XmlDataFormatter(Configuration.MonitorConfiguration monitorConfiguration)
38 | {
39 | this.conf = monitorConfiguration;
40 | }
41 |
42 | public IDictionary ToXml(IDictionary data)
43 | {
44 | var dataStr = DataFormatHelper.ToXml(data);
45 | dataStr = DataFormatHelper.Base64Encode(dataStr);
46 | var dataChunks = DataFormatHelper.PackString(dataStr, this.conf.MaxValueLength <= 0 ? DEFAULT_VALUE_LENGTH : this.conf.MaxValueLength);
47 | var packedData = DataFormatHelper.ToChunk(this.conf.DataItemKeyPrefix, dataChunks, DataFormatHelper.ToXml);
48 | return packedData;
49 | }
50 | }
51 | }
52 |
--------------------------------------------------------------------------------
/src/UnitTest/TestToXmlExpectedOutput.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
25 | Dictionary(JSON object) to Xml Test
26 |
27 | - Case1: String as Field
28 | - Case2: String Array as Field
29 | - Case3: Dictionary as Field
30 | - Case4: Object Array as Field
31 | - Case5: Null
32 |
33 |
34 | Key name as XElement name
35 | String content as XElement content
36 | Each element becomes a child XElement with name 'Item'
37 | Dictionary becomes a child XElement
38 |
39 | - 1. Each element in the array is a dictionary
40 | - 2. The 1st dictionary itself contains an array field
41 | - 3. The 2nd dictionary itself contains a dictionary
42 |
43 | Output 'null'
44 |
45 |
46 | -
47 |
48 |
- Element 1
49 | - Element 1
50 |
51 |
52 | -
53 |
54 | ObjectValue
55 |
56 |
57 |
58 | null
59 |
60 |
--------------------------------------------------------------------------------
/src/Service/EnhacedMonitoringProvider.Designer.cs:
--------------------------------------------------------------------------------
1 | //The MIT License (MIT)
2 | //
3 | //Copyright 2015 Microsoft Corporation
4 | //
5 | //Permission is hereby granted, free of charge, to any person obtaining a copy
6 | //of this software and associated documentation files (the "Software"), to deal
7 | //in the Software without restriction, including without limitation the rights
8 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | //copies of the Software, and to permit persons to whom the Software is
10 | //furnished to do so, subject to the following conditions:
11 | //
12 | //The above copyright notice and this permission notice shall be included in
13 | //all copies or substantial portions of the Software.
14 | //
15 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | //THE SOFTWARE.
22 | //
23 | namespace EnhancedMonitoring.Service
24 | {
25 | partial class EnhacedMonitoring
26 | {
27 | ///
28 | /// Required designer variable.
29 | ///
30 | private System.ComponentModel.IContainer components = null;
31 |
32 | ///
33 | /// Clean up any resources being used.
34 | ///
35 | /// true if managed resources should be disposed; otherwise, false.
36 | protected override void Dispose(bool disposing)
37 | {
38 | if (disposing && (components != null))
39 | {
40 | components.Dispose();
41 | }
42 | base.Dispose(disposing);
43 | }
44 |
45 | #region Component Designer generated code
46 |
47 | ///
48 | /// Required method for Designer support - do not modify
49 | /// the contents of this method with the code editor.
50 | ///
51 | private void InitializeComponent()
52 | {
53 | //
54 | // EnhacedMonitoring
55 | //
56 | this.ServiceName = "Enhanced Monitoring Provider Service";
57 |
58 | }
59 |
60 | #endregion
61 | }
62 | }
63 |
--------------------------------------------------------------------------------
/src/EnhancedMonitoring/DataCollector/MgmtObject.cs:
--------------------------------------------------------------------------------
1 | //The MIT License (MIT)
2 | //
3 | //Copyright 2015 Microsoft Corporation
4 | //
5 | //Permission is hereby granted, free of charge, to any person obtaining a copy
6 | //of this software and associated documentation files (the "Software"), to deal
7 | //in the Software without restriction, including without limitation the rights
8 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | //copies of the Software, and to permit persons to whom the Software is
10 | //furnished to do so, subject to the following conditions:
11 | //
12 | //The above copyright notice and this permission notice shall be included in
13 | //all copies or substantial portions of the Software.
14 | //
15 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | //THE SOFTWARE.
22 | //
23 | using EnhancedMonitoring.Configuration;
24 | using System;
25 | using System.Collections.Generic;
26 | using System.Linq;
27 | using System.Management;
28 | using System.Text;
29 | using System.Threading.Tasks;
30 |
31 | namespace EnhancedMonitoring.DataCollector
32 | {
33 | public abstract class MgmtObject
34 | {
35 |
36 | public static MgmtObject CreateInstance(MgmtObjectConfiguration conf)
37 | {
38 | if(conf == null)
39 | {
40 | throw new ArgumentNullException("conf");
41 | }
42 |
43 | if(conf.Type == MgmtObjectType.DynamicMemory)
44 | {
45 | return new DynamicMemoryMgmtObject(conf);
46 | }
47 | return new QueryMgmtObject(conf);
48 | }
49 |
50 | protected MgmtObjectConfiguration conf;
51 |
52 | protected MgmtObject(MgmtObjectConfiguration conf)
53 | {
54 | this.conf = conf;
55 | }
56 |
57 | public abstract Object CollectData(IDictionary args);
58 |
59 | public abstract String KeyName { get; }
60 |
61 | public bool SuppressError
62 | {
63 | get
64 | {
65 | return this.conf.SuppressError;
66 | }
67 | }
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/src/UnitTest/Properties/AssemblyInfo.cs:
--------------------------------------------------------------------------------
1 | //The MIT License (MIT)
2 | //
3 | //Copyright 2015 Microsoft Corporation
4 | //
5 | //Permission is hereby granted, free of charge, to any person obtaining a copy
6 | //of this software and associated documentation files (the "Software"), to deal
7 | //in the Software without restriction, including without limitation the rights
8 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | //copies of the Software, and to permit persons to whom the Software is
10 | //furnished to do so, subject to the following conditions:
11 | //
12 | //The above copyright notice and this permission notice shall be included in
13 | //all copies or substantial portions of the Software.
14 | //
15 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | //THE SOFTWARE.
22 | //
23 | using System.Reflection;
24 | using System.Runtime.CompilerServices;
25 | using System.Runtime.InteropServices;
26 |
27 | // General Information about an assembly is controlled through the following
28 | // set of attributes. Change these attribute values to modify the information
29 | // associated with an assembly.
30 | [assembly: AssemblyTitle("UnitTest")]
31 | [assembly: AssemblyDescription("")]
32 | [assembly: AssemblyConfiguration("")]
33 | [assembly: AssemblyCompany("")]
34 | [assembly: AssemblyProduct("UnitTest")]
35 | [assembly: AssemblyCopyright("Copyright © 2014")]
36 | [assembly: AssemblyTrademark("")]
37 | [assembly: AssemblyCulture("")]
38 |
39 | // Setting ComVisible to false makes the types in this assembly not visible
40 | // to COM components. If you need to access a type in this assembly from
41 | // COM, set the ComVisible attribute to true on that type.
42 | [assembly: ComVisible(false)]
43 |
44 | // The following GUID is for the ID of the typelib if this project is exposed to COM
45 | [assembly: Guid("5a308b21-7d9c-49d0-a903-88001f52deac")]
46 |
47 | // Version information for an assembly consists of the following four values:
48 | //
49 | // Major Version
50 | // Minor Version
51 | // Build Number
52 | // Revision
53 | //
54 | // You can specify all the values or you can default the Build and Revision Numbers
55 | // by using the '*' as shown below:
56 | // [assembly: AssemblyVersion("1.0.*")]
57 | [assembly: AssemblyVersion("1.0.0.0")]
58 | [assembly: AssemblyFileVersion("1.0.0.0")]
59 |
--------------------------------------------------------------------------------
/src/UnitTest/WMIQueryHelperTest.cs:
--------------------------------------------------------------------------------
1 | //The MIT License (MIT)
2 | //
3 | //Copyright 2015 Microsoft Corporation
4 | //
5 | //Permission is hereby granted, free of charge, to any person obtaining a copy
6 | //of this software and associated documentation files (the "Software"), to deal
7 | //in the Software without restriction, including without limitation the rights
8 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | //copies of the Software, and to permit persons to whom the Software is
10 | //furnished to do so, subject to the following conditions:
11 | //
12 | //The above copyright notice and this permission notice shall be included in
13 | //all copies or substantial portions of the Software.
14 | //
15 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | //THE SOFTWARE.
22 | //
23 | using System;
24 | using System.Text;
25 | using System.Collections.Generic;
26 | using Microsoft.VisualStudio.TestTools.UnitTesting;
27 | using EnhancedMonitoring;
28 |
29 | namespace UnitTest
30 | {
31 | [TestClass]
32 | public class WMIQueryHelperTest
33 | {
34 |
35 | [TestMethod]
36 | public void TestEscapeQuery()
37 | {
38 | var condition = WMIQueryHelper.EscapeLikeCondition(@"[");
39 | Assert.AreEqual(@"[[]", condition);
40 | condition = WMIQueryHelper.EscapeLikeCondition(@"_");
41 | Assert.AreEqual(@"[_]", condition);
42 | condition = WMIQueryHelper.EscapeLikeCondition(@"%");
43 | Assert.AreEqual(@"[%]", condition);
44 |
45 | condition = WMIQueryHelper.EscapeLikeCondition(@"^");
46 | Assert.AreEqual(@"^", condition);
47 | condition = WMIQueryHelper.EscapeLikeCondition(@"]");
48 | Assert.AreEqual(@"]", condition);
49 |
50 | condition = WMIQueryHelper.EscapeLikeCondition(@"[[[][]]]");
51 | Assert.AreEqual(@"[[][[][[]][[]]]]", condition);
52 |
53 | condition = WMIQueryHelper.EscapeLikeCondition(@"[_]");
54 | Assert.AreEqual(@"[[][_]]", condition);
55 |
56 | condition = WMIQueryHelper.EscapeLikeCondition(@"");
57 | Assert.AreEqual(@"", condition);
58 |
59 | condition = WMIQueryHelper.EscapeLikeCondition(null);
60 | Assert.AreEqual(null, condition);
61 | }
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/src/EnhancedMonitoring/Configuration/MgmtObjectConfiguration.cs:
--------------------------------------------------------------------------------
1 | //The MIT License (MIT)
2 | //
3 | //Copyright 2015 Microsoft Corporation
4 | //
5 | //Permission is hereby granted, free of charge, to any person obtaining a copy
6 | //of this software and associated documentation files (the "Software"), to deal
7 | //in the Software without restriction, including without limitation the rights
8 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | //copies of the Software, and to permit persons to whom the Software is
10 | //furnished to do so, subject to the following conditions:
11 | //
12 | //The above copyright notice and this permission notice shall be included in
13 | //all copies or substantial portions of the Software.
14 | //
15 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | //THE SOFTWARE.
22 | //
23 | using System;
24 | using System.Collections.Generic;
25 | using System.Linq;
26 | using System.Text;
27 | using System.Threading.Tasks;
28 | using System.Xml.Serialization;
29 |
30 | namespace EnhancedMonitoring.Configuration
31 | {
32 | [XmlRoot("MgmtObject")]
33 | public class MgmtObjectConfiguration
34 | {
35 | [XmlAttribute("Type")]
36 | public MgmtObjectType Type { get; set; }
37 |
38 | [XmlAttribute("SuppressError")]
39 | public Boolean SuppressError { get; set; }
40 |
41 | [XmlAttribute("ReturnValue")]
42 | public MgmtObjectReturnValueType ReturnValueType { get; set; }
43 |
44 | [XmlElement("Namespace")]
45 | public String Namespace { get; set; }
46 |
47 | [XmlElement("From")]
48 | public String From { get; set; }
49 |
50 | [XmlElement("As")]
51 | public String As { get; set; }
52 |
53 | [XmlElement("Where")]
54 | public String Where { get; set; }
55 |
56 | [XmlArray("WhereArgs")]
57 | [XmlArrayItem("WhereArg")]
58 | public WhereArgList WhereArgs { get; set; }
59 |
60 | [XmlArray("PerfCounters")]
61 | [XmlArrayItem("PerfCounter")]
62 | public PerfCounterConfigurationList PerfCounters { get; set; }
63 |
64 | }
65 |
66 | public class WhereArgList : List
67 | {
68 |
69 | }
70 |
71 | public class PerfCounterConfigurationList : List
72 | {
73 |
74 | }
75 |
76 | }
77 |
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | ## Security
4 |
5 | Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/).
6 |
7 | If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below.
8 |
9 | ## Reporting Security Issues
10 |
11 | **Please do not report security vulnerabilities through public GitHub issues.**
12 |
13 | Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report).
14 |
15 | If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey).
16 |
17 | You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc).
18 |
19 | Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:
20 |
21 | * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
22 | * Full paths of source file(s) related to the manifestation of the issue
23 | * The location of the affected source code (tag/branch/commit or direct URL)
24 | * Any special configuration required to reproduce the issue
25 | * Step-by-step instructions to reproduce the issue
26 | * Proof-of-concept or exploit code (if possible)
27 | * Impact of the issue, including how an attacker might exploit the issue
28 |
29 | This information will help us triage your report more quickly.
30 |
31 | If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs.
32 |
33 | ## Preferred Languages
34 |
35 | We prefer all communications to be in English.
36 |
37 | ## Policy
38 |
39 | Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd).
40 |
41 |
42 |
--------------------------------------------------------------------------------
/src/UnitTest/SupportedVMDetectorTest.cs:
--------------------------------------------------------------------------------
1 | //The MIT License (MIT)
2 | //
3 | //Copyright 2015 Microsoft Corporation
4 | //
5 | //Permission is hereby granted, free of charge, to any person obtaining a copy
6 | //of this software and associated documentation files (the "Software"), to deal
7 | //in the Software without restriction, including without limitation the rights
8 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | //copies of the Software, and to permit persons to whom the Software is
10 | //furnished to do so, subject to the following conditions:
11 | //
12 | //The above copyright notice and this permission notice shall be included in
13 | //all copies or substantial portions of the Software.
14 | //
15 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | //THE SOFTWARE.
22 | //
23 | using System;
24 | using System.Linq;
25 | using Microsoft.VisualStudio.TestTools.UnitTesting;
26 | using EnhancedMonitoring;
27 | using EnhancedMonitoring.Configuration;
28 | using System.Collections.Generic;
29 |
30 | namespace UnitTest
31 | {
32 | [TestClass]
33 | public class SupportedVMDetectorTest
34 | {
35 | ///
36 | /// This test requires the host has at least one virtual machine to pass.
37 | ///
38 | [TestMethod]
39 | public void TestDetectSupportedVM()
40 | {
41 | DetectSupportedVM();
42 | }
43 |
44 | public IDictionary DetectSupportedVM()
45 | {
46 | var detector = SupportedVMDetector.CreateInstance(new SupportedVMDetectorConfiguration()
47 | {
48 | GuestDataItemKey = "Enhanced_Monitoring_Supported",
49 | });
50 |
51 | var watcher = System.Diagnostics.Stopwatch.StartNew();
52 | var vms = detector.GetSupportedVM();
53 | Console.WriteLine(String.Format("Elapsed: {0}ms\t Detect supported VM", watcher.ElapsedMilliseconds));
54 |
55 | Assert.IsNotNull(vms);
56 | Assert.AreNotEqual(0, vms.Count);
57 |
58 | var vm = vms.FirstOrDefault();
59 | Assert.IsNotNull(vm);
60 | Assert.IsNotNull(vm["VirtualMachineName"]);
61 | Assert.IsNotNull(vm["VirtualMachineElementName"]);
62 | Assert.IsNotNull(vm["VirtualMachinePath"]);
63 | Console.WriteLine("Found: " + vm["VirtualMachineElementName"]);
64 | return vm;
65 | }
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/src/UnitTest/DynamicMemoryMgmtObjectTest.cs:
--------------------------------------------------------------------------------
1 | //The MIT License (MIT)
2 | //
3 | //Copyright 2015 Microsoft Corporation
4 | //
5 | //Permission is hereby granted, free of charge, to any person obtaining a copy
6 | //of this software and associated documentation files (the "Software"), to deal
7 | //in the Software without restriction, including without limitation the rights
8 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | //copies of the Software, and to permit persons to whom the Software is
10 | //furnished to do so, subject to the following conditions:
11 | //
12 | //The above copyright notice and this permission notice shall be included in
13 | //all copies or substantial portions of the Software.
14 | //
15 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | //THE SOFTWARE.
22 | //
23 | using System;
24 | using Microsoft.VisualStudio.TestTools.UnitTesting;
25 | using EnhancedMonitoring.Configuration;
26 | using EnhancedMonitoring.DataCollector;
27 | using EnhancedMonitoring;
28 | using System.Collections.Generic;
29 | using System.Management;
30 | using System.Linq;
31 |
32 | namespace UnitTest
33 | {
34 | ///
35 | /// Summary description for DynamicMemoryMgmtObjectTest
36 | ///
37 | [TestClass]
38 | public class DynamicMemoryMgmtObjectTest
39 | {
40 |
41 | [TestMethod]
42 | public MgmtObject TestDynamicMemoryMgmtObject()
43 | {
44 | MgmtObjectConfiguration conf = new MgmtObjectConfiguration()
45 | {
46 | Type = MgmtObjectType.DynamicMemory,
47 | };
48 |
49 | var mgmtObj = MgmtObject.CreateInstance(conf);
50 | Assert.IsNotNull(mgmtObj);
51 | Assert.IsTrue(mgmtObj is DynamicMemoryMgmtObject);
52 | return mgmtObj;
53 | }
54 |
55 | [TestMethod]
56 | public void TestDynamicMemoryMgmtObjectCollectData()
57 | {
58 | var mgmtObj = TestDynamicMemoryMgmtObject();
59 | var vmArgs = new SupportedVMDetectorTest().DetectSupportedVM();
60 | var data = mgmtObj.CollectData(vmArgs);
61 |
62 | Assert.IsNotNull(data);
63 | var dynamicMemoryData = (data as Dictionary);
64 | Assert.IsNotNull(dynamicMemoryData);
65 | Assert.IsNotNull(dynamicMemoryData[DynamicMemoryMgmtObject.KeyName_MemoryUsage]);
66 | Assert.IsNotNull(dynamicMemoryData[DynamicMemoryMgmtObject.KeyName_MemoryAvailable]);
67 | Assert.IsNotNull(dynamicMemoryData[DynamicMemoryMgmtObject.KeyName_AvailableMemoryBuffer]);
68 | }
69 | }
70 | }
71 |
--------------------------------------------------------------------------------
/src/EnhancedMonitoring.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio 2013
4 | VisualStudioVersion = 12.0.21005.1
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTest", "UnitTest\UnitTest.csproj", "{0B568E5B-3796-47CC-B934-C4684CBE241C}"
7 | EndProject
8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Service", "Service\Service.csproj", "{ED1F3B96-683F-4D16-B4F9-06765E3697C1}"
9 | EndProject
10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EnhancedMonitoring", "EnhancedMonitoring\EnhancedMonitoring.csproj", "{7EACC378-2947-4F2E-AB0F-EB57BE7D3680}"
11 | EndProject
12 | Project("{930C7802-8A8C-48F9-8165-68863BCCD9DD}") = "Setup", "..\packages\MSI\EnhancedMonitoring\Setup.wixproj", "{A6AA397B-1031-4FBF-9A8A-B50EE7318EC6}"
13 | ProjectSection(ProjectDependencies) = postProject
14 | {7EACC378-2947-4F2E-AB0F-EB57BE7D3680} = {7EACC378-2947-4F2E-AB0F-EB57BE7D3680}
15 | {ED1F3B96-683F-4D16-B4F9-06765E3697C1} = {ED1F3B96-683F-4D16-B4F9-06765E3697C1}
16 | EndProjectSection
17 | EndProject
18 | Global
19 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
20 | Debug|x64 = Debug|x64
21 | DebugAndRelease|x64 = DebugAndRelease|x64
22 | Release|x64 = Release|x64
23 | EndGlobalSection
24 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
25 | {0B568E5B-3796-47CC-B934-C4684CBE241C}.Debug|x64.ActiveCfg = Debug|Any CPU
26 | {0B568E5B-3796-47CC-B934-C4684CBE241C}.Debug|x64.Build.0 = Debug|Any CPU
27 | {0B568E5B-3796-47CC-B934-C4684CBE241C}.DebugAndRelease|x64.ActiveCfg = DebugAndRelease|Any CPU
28 | {0B568E5B-3796-47CC-B934-C4684CBE241C}.Release|x64.ActiveCfg = Release|Any CPU
29 | {ED1F3B96-683F-4D16-B4F9-06765E3697C1}.Debug|x64.ActiveCfg = Debug|x64
30 | {ED1F3B96-683F-4D16-B4F9-06765E3697C1}.Debug|x64.Build.0 = Debug|x64
31 | {ED1F3B96-683F-4D16-B4F9-06765E3697C1}.DebugAndRelease|x64.ActiveCfg = DebugAndRelease|x64
32 | {ED1F3B96-683F-4D16-B4F9-06765E3697C1}.DebugAndRelease|x64.Build.0 = DebugAndRelease|x64
33 | {ED1F3B96-683F-4D16-B4F9-06765E3697C1}.Release|x64.ActiveCfg = Release|x64
34 | {ED1F3B96-683F-4D16-B4F9-06765E3697C1}.Release|x64.Build.0 = Release|x64
35 | {7EACC378-2947-4F2E-AB0F-EB57BE7D3680}.Debug|x64.ActiveCfg = Debug|x64
36 | {7EACC378-2947-4F2E-AB0F-EB57BE7D3680}.Debug|x64.Build.0 = Debug|x64
37 | {7EACC378-2947-4F2E-AB0F-EB57BE7D3680}.DebugAndRelease|x64.ActiveCfg = DebugAndRelease|x64
38 | {7EACC378-2947-4F2E-AB0F-EB57BE7D3680}.DebugAndRelease|x64.Build.0 = DebugAndRelease|x64
39 | {7EACC378-2947-4F2E-AB0F-EB57BE7D3680}.Release|x64.ActiveCfg = Release|x64
40 | {7EACC378-2947-4F2E-AB0F-EB57BE7D3680}.Release|x64.Build.0 = Release|x64
41 | {A6AA397B-1031-4FBF-9A8A-B50EE7318EC6}.Debug|x64.ActiveCfg = Debug|x64
42 | {A6AA397B-1031-4FBF-9A8A-B50EE7318EC6}.Debug|x64.Build.0 = Debug|x64
43 | {A6AA397B-1031-4FBF-9A8A-B50EE7318EC6}.DebugAndRelease|x64.ActiveCfg = DebugAndRelease|x86
44 | {A6AA397B-1031-4FBF-9A8A-B50EE7318EC6}.Release|x64.ActiveCfg = Release|x86
45 | EndGlobalSection
46 | GlobalSection(SolutionProperties) = preSolution
47 | HideSolutionNode = FALSE
48 | EndGlobalSection
49 | EndGlobal
50 |
--------------------------------------------------------------------------------
/src/UnitTest/MonitorConfigurationTest.cs:
--------------------------------------------------------------------------------
1 | //The MIT License (MIT)
2 | //
3 | //Copyright 2015 Microsoft Corporation
4 | //
5 | //Permission is hereby granted, free of charge, to any person obtaining a copy
6 | //of this software and associated documentation files (the "Software"), to deal
7 | //in the Software without restriction, including without limitation the rights
8 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | //copies of the Software, and to permit persons to whom the Software is
10 | //furnished to do so, subject to the following conditions:
11 | //
12 | //The above copyright notice and this permission notice shall be included in
13 | //all copies or substantial portions of the Software.
14 | //
15 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | //THE SOFTWARE.
22 | //
23 | using System;
24 | using System.Linq;
25 | using Microsoft.VisualStudio.TestTools.UnitTesting;
26 | using EnhancedMonitoring.Configuration;
27 |
28 | namespace UnitTest
29 | {
30 | [TestClass]
31 | public class MonitorConfigurationTest
32 | {
33 | [TestMethod]
34 | public void TestLoadConfiguration()
35 | {
36 | var conf = MonitorConfiguration.Load(@"..\..\SampleMonitor.xml");
37 |
38 | Assert.IsNotNull(conf);
39 | Assert.IsNotNull(conf.Version);
40 | Console.WriteLine(conf.Version);
41 | Assert.AreEqual(60, conf.RefreshRate);
42 | Assert.AreEqual(700, conf.MaxValueLength);
43 | Assert.IsNotNull(conf.Kvp);
44 | Assert.AreEqual(200, conf.Kvp.WriteInterval);
45 | Assert.IsTrue(conf.Kvp.BatchMode);
46 |
47 | Assert.IsNotNull(conf.SupportedVMDetector);
48 | Assert.IsNotNull(conf.SupportedVMDetector.GuestDataItemKey);
49 |
50 | Assert.IsNotNull(conf.MgmtObjects);
51 | var mgmtObj = conf.MgmtObjects.FirstOrDefault();
52 | Assert.IsNotNull(mgmtObj);
53 | Assert.IsTrue(mgmtObj.SuppressError);
54 | Assert.IsNotNull(mgmtObj.Namespace);
55 | Assert.IsNotNull(mgmtObj.Where);
56 | Assert.IsNotNull(mgmtObj.From);
57 | Assert.IsNotNull(mgmtObj.WhereArgs);
58 | Assert.IsTrue(mgmtObj.WhereArgs.FirstOrDefault().Escape);
59 | Assert.IsNotNull(mgmtObj.WhereArgs.FirstOrDefault());
60 |
61 | Assert.IsNotNull(mgmtObj.PerfCounters);
62 | var counter = mgmtObj.PerfCounters.FirstOrDefault();
63 | Assert.IsNotNull(counter);
64 | Assert.IsNotNull(counter.Select);
65 | Assert.IsNotNull(counter.As);
66 |
67 | var dynamicMemMgmtObj = conf.MgmtObjects.Where(m => m.Type == MgmtObjectType.DynamicMemory).FirstOrDefault();
68 | Assert.IsNotNull(dynamicMemMgmtObj);
69 | Assert.AreEqual(MgmtObjectReturnValueType.Single, dynamicMemMgmtObj.ReturnValueType);
70 | }
71 | }
72 | }
73 |
--------------------------------------------------------------------------------
/src/UnitTest/DataPackingHelperTest.cs:
--------------------------------------------------------------------------------
1 | //The MIT License (MIT)
2 | //
3 | //Copyright 2015 Microsoft Corporation
4 | //
5 | //Permission is hereby granted, free of charge, to any person obtaining a copy
6 | //of this software and associated documentation files (the "Software"), to deal
7 | //in the Software without restriction, including without limitation the rights
8 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | //copies of the Software, and to permit persons to whom the Software is
10 | //furnished to do so, subject to the following conditions:
11 | //
12 | //The above copyright notice and this permission notice shall be included in
13 | //all copies or substantial portions of the Software.
14 | //
15 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | //THE SOFTWARE.
22 | //
23 | using System;
24 | using Microsoft.VisualStudio.TestTools.UnitTesting;
25 | using EnhancedMonitoring.DataFormat;
26 | using System.Collections.Generic;
27 |
28 | namespace UnitTest
29 | {
30 | [TestClass]
31 | public class DataPackingHelperTest
32 | {
33 | [TestMethod]
34 | public void TestPackString()
35 | {
36 | {
37 | var rawStr = "aaaa";
38 | var result = DataFormatHelper.PackString(rawStr, 1);
39 | Assert.IsNotNull(result);
40 | Assert.AreEqual(4, result.Count);
41 | }
42 |
43 | {
44 | var rawStr = "aaaa";
45 | var result = DataFormatHelper.PackString(rawStr, 3);
46 | Assert.IsNotNull(result);
47 | Assert.AreEqual(2, result.Count);
48 | }
49 |
50 | {
51 | var rawStr = "aaaa";
52 | var result = DataFormatHelper.PackString(rawStr, 5);
53 | Assert.IsNotNull(result);
54 | Assert.AreEqual(1, result.Count);
55 | }
56 | }
57 |
58 | [TestMethod]
59 | public void TestPackData()
60 | {
61 | var data = new Dictionary()
62 | {
63 | {"MaxClockFrequency", 100000},
64 | {"AvailableMemeory", 1024},
65 | };
66 | foreach (var kvp in data)
67 | {
68 | Console.WriteLine(kvp);
69 | }
70 | var dataStr = DataFormatHelper.ToXml(data);
71 | Console.WriteLine(dataStr);
72 |
73 | dataStr = DataFormatHelper.Base64Encode(dataStr);
74 | Console.WriteLine(dataStr);
75 |
76 | var dataChunks = DataFormatHelper.PackString(dataStr, 50);
77 |
78 | var packedData = DataFormatHelper.ToChunk("Part_", dataChunks, DataFormatHelper.ToXml);
79 | foreach(var kvp in packedData)
80 | {
81 | Console.WriteLine(kvp);
82 | }
83 |
84 | Assert.AreEqual(3, packedData.Count);
85 | }
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/src/EnhancedMonitoring/Configuration/MonitorConfiguration.cs:
--------------------------------------------------------------------------------
1 | //The MIT License (MIT)
2 | //
3 | //Copyright 2015 Microsoft Corporation
4 | //
5 | //Permission is hereby granted, free of charge, to any person obtaining a copy
6 | //of this software and associated documentation files (the "Software"), to deal
7 | //in the Software without restriction, including without limitation the rights
8 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | //copies of the Software, and to permit persons to whom the Software is
10 | //furnished to do so, subject to the following conditions:
11 | //
12 | //The above copyright notice and this permission notice shall be included in
13 | //all copies or substantial portions of the Software.
14 | //
15 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | //THE SOFTWARE.
22 | //
23 | using System;
24 | using System.Collections.Generic;
25 | using System.IO;
26 | using System.Linq;
27 | using System.Text;
28 | using System.Threading.Tasks;
29 | using System.Xml.Serialization;
30 |
31 | namespace EnhancedMonitoring.Configuration
32 | {
33 | [XmlRoot("Monitor")]
34 | public class MonitorConfiguration
35 | {
36 | [XmlElement("RefreshRate")]
37 | public Int64 RefreshRate { get; set; }
38 |
39 | [XmlElement("Version")]
40 | public String Version { get; set; }
41 |
42 | [XmlElement("MaxValueLength")]
43 | public Int32 MaxValueLength { get; set; }
44 |
45 | [XmlElement("Kvp")]
46 | public KvpConfiguration Kvp { get; set; }
47 |
48 | [XmlElement("LogLevel")]
49 | public String LogLevel { get; set; }
50 |
51 | [XmlElement("LogFilePath")]
52 | public String LogFilePath { get; set; }
53 |
54 | [XmlElement("MaxLogRetain")]
55 | public Int32 MaxLogRetention { get; set; }
56 |
57 | [XmlElement("LogFileSize")]
58 | public Int64 LogFileSize { get; set; }
59 |
60 | public Double EventLogInterval { get; set; }
61 |
62 | [XmlElement("DataItemKeyPrefix")]
63 | public string DataItemKeyPrefix { get; set; }
64 |
65 | [XmlElement("SupportedVMDetector")]
66 | public SupportedVMDetectorConfiguration SupportedVMDetector { get; set; }
67 |
68 | [XmlArray("MgmtObjects")]
69 | [XmlArrayItem("MgmtObject")]
70 | public MgmtObjectConfigurationList MgmtObjects { get; set; }
71 |
72 | public static MonitorConfiguration Load(String path)
73 | {
74 | XmlSerializer serializer = new XmlSerializer(typeof(MonitorConfiguration));
75 | using(FileStream fs = new FileStream(path, FileMode.Open, FileAccess.Read))
76 | {
77 | var conf = serializer.Deserialize(fs);
78 | return (MonitorConfiguration)conf;
79 | }
80 | }
81 | }
82 |
83 | public class VirtualMachineList : List
84 | {
85 |
86 | }
87 |
88 | public class MgmtObjectConfigurationList : List
89 | {
90 |
91 | }
92 | }
93 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.sln.docstates
8 |
9 | # Build results
10 | [Dd]ebug/
11 | [Dd]ebugPublic/
12 | [Rr]elease/
13 | [Rr]eleases/
14 | x64/
15 | build/
16 | bld/
17 | [Bb]in/
18 | [Oo]bj/
19 |
20 | # Roslyn cache directories
21 | *.ide/
22 |
23 | # MSTest test Results
24 | [Tt]est[Rr]esult*/
25 | [Bb]uild[Ll]og.*
26 |
27 | #NUNIT
28 | *.VisualState.xml
29 | TestResult.xml
30 |
31 | # Build Results of an ATL Project
32 | [Dd]ebugPS/
33 | [Rr]eleasePS/
34 | dlldata.c
35 |
36 | *_i.c
37 | *_p.c
38 | *_i.h
39 | *.ilk
40 | *.meta
41 | *.obj
42 | *.pch
43 | *.pdb
44 | *.pgc
45 | *.pgd
46 | *.rsp
47 | *.sbr
48 | *.tlb
49 | *.tli
50 | *.tlh
51 | *.tmp
52 | *.tmp_proj
53 | *.log
54 | *.vspscc
55 | *.vssscc
56 | .builds
57 | *.pidb
58 | *.svclog
59 | *.scc
60 |
61 | # Chutzpah Test files
62 | _Chutzpah*
63 |
64 | # Visual C++ cache files
65 | ipch/
66 | *.aps
67 | *.ncb
68 | *.opensdf
69 | *.sdf
70 | *.cachefile
71 |
72 | # Visual Studio profiler
73 | *.psess
74 | *.vsp
75 | *.vspx
76 |
77 | # TFS 2012 Local Workspace
78 | $tf/
79 |
80 | # Guidance Automation Toolkit
81 | *.gpState
82 |
83 | # ReSharper is a .NET coding add-in
84 | _ReSharper*/
85 | *.[Rr]e[Ss]harper
86 | *.DotSettings.user
87 |
88 | # JustCode is a .NET coding addin-in
89 | .JustCode
90 |
91 | # TeamCity is a build add-in
92 | _TeamCity*
93 |
94 | # DotCover is a Code Coverage Tool
95 | *.dotCover
96 |
97 | # NCrunch
98 | _NCrunch_*
99 | .*crunch*.local.xml
100 |
101 | # MightyMoose
102 | *.mm.*
103 | AutoTest.Net/
104 |
105 | # Web workbench (sass)
106 | .sass-cache/
107 |
108 | # Installshield output folder
109 | [Ee]xpress/
110 |
111 | # DocProject is a documentation generator add-in
112 | DocProject/buildhelp/
113 | DocProject/Help/*.HxT
114 | DocProject/Help/*.HxC
115 | DocProject/Help/*.hhc
116 | DocProject/Help/*.hhk
117 | DocProject/Help/*.hhp
118 | DocProject/Help/Html2
119 | DocProject/Help/html
120 |
121 | # Click-Once directory
122 | publish/
123 |
124 | # Publish Web Output
125 | *.[Pp]ublish.xml
126 | *.azurePubxml
127 | ## TODO: Comment the next line if you want to checkin your
128 | ## web deploy settings but do note that will include unencrypted
129 | ## passwords
130 | *.pubxml
131 |
132 | # Enable "build/" folder in the NuGet Packages folder since
133 | # NuGet packages use it for MSBuild targets.
134 | # This line needs to be after the ignore of the build folder
135 | # (and the packages folder if the line above has been uncommented)
136 | !packages/build/
137 |
138 | # Windows Azure Build Output
139 | csx/
140 | *.build.csdef
141 |
142 | # Windows Store app package directory
143 | AppPackages/
144 |
145 | # Others
146 | sql/
147 | *.Cache
148 | ClientBin/
149 | [Ss]tyle[Cc]op.*
150 | ~$*
151 | *~
152 | *.dbmdl
153 | *.dbproj.schemaview
154 | *.pfx
155 | *.publishsettings
156 | node_modules/
157 |
158 | # RIA/Silverlight projects
159 | Generated_Code/
160 |
161 | # Backup & report files from converting an old project file
162 | # to a newer Visual Studio version. Backup files are not needed,
163 | # because we have git ;-)
164 | _UpgradeReport_Files/
165 | Backup*/
166 | UpgradeLog*.XML
167 | UpgradeLog*.htm
168 |
169 | # SQL Server files
170 | *.mdf
171 | *.ldf
172 |
173 | # Business Intelligence projects
174 | *.rdl.data
175 | *.bim.layout
176 | *.bim_*.settings
177 |
178 | # Microsoft Fakes
179 | FakesAssemblies/
180 |
181 | #Source Depo
182 | build*.prf
183 | build*.trc
184 | build*.err
185 | sources
186 | sources.dep
187 | dirs
188 | project.mk
--------------------------------------------------------------------------------
/src/EnhancedMonitoring/NamedArgumentHelper.cs:
--------------------------------------------------------------------------------
1 | //The MIT License (MIT)
2 | //
3 | //Copyright 2015 Microsoft Corporation
4 | //
5 | //Permission is hereby granted, free of charge, to any person obtaining a copy
6 | //of this software and associated documentation files (the "Software"), to deal
7 | //in the Software without restriction, including without limitation the rights
8 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | //copies of the Software, and to permit persons to whom the Software is
10 | //furnished to do so, subject to the following conditions:
11 | //
12 | //The above copyright notice and this permission notice shall be included in
13 | //all copies or substantial portions of the Software.
14 | //
15 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | //THE SOFTWARE.
22 | //
23 | using EnhancedMonitoring.Configuration;
24 | using System;
25 | using System.Collections.Generic;
26 | using System.Linq;
27 | using System.Text;
28 | using System.Threading.Tasks;
29 |
30 | namespace EnhancedMonitoring
31 | {
32 | public static class NamedArgumentHelper
33 | {
34 | public static String Resolve(String str, IList whereArgs, IDictionary args)
35 | {
36 | if (String.IsNullOrEmpty(str))
37 | {
38 | return str;
39 | }
40 |
41 | if(whereArgs == null || whereArgs.Count == 0)
42 | {
43 | try
44 | {
45 | return String.Format(str, new Object[0]);
46 | }
47 | catch(FormatException e)
48 | {
49 | throw new ArgumentException(String.Format("format={0}, args=NullOrEmpty", str), e);
50 | }
51 | }
52 |
53 | if(args == null && whereArgs != null && whereArgs.Count > 0)
54 | {
55 | throw new ArgumentException(String.Format("Can't resolve argument: format={0}, args={1}", str, String.Join(",", whereArgs.Select(a => a.Name))));
56 | }
57 |
58 | Object[] argsVal = new Object[args.Count];
59 |
60 | for (int i = 0; i < whereArgs.Count; i++)
61 | {
62 | var whereArg = whereArgs[i];
63 | if (args.ContainsKey(whereArg.Name))
64 | {
65 | argsVal[i] = args[whereArg.Name];
66 | if(whereArg.Escape && argsVal[i] != null)
67 | {
68 | argsVal[i] = WMIQueryHelper.EscapeLikeCondition(argsVal[i].ToString());
69 | }
70 | }
71 | else
72 | {
73 | throw new ArgumentException(String.Format("Can't resolve argument format={0}, args={1}", str, whereArgs[i].Name));
74 | }
75 | }
76 |
77 | try
78 | {
79 | return String.Format(str, argsVal);
80 | }
81 | catch(FormatException e)
82 | {
83 | throw new ArgumentException(String.Format("Can't resolve argument: format={0}, args={1}", str, String.Join(",", whereArgs)), e);
84 | }
85 | }
86 | }
87 | }
88 |
--------------------------------------------------------------------------------
/src/UnitTest/SampleResult.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | -
4 | 331819225422
5 | 4627899239734
6 | 2294591080835
7 | 3312782
8 |
9 |
10 |
11 | -
12 | 5956484
13 | 51824588
14 | 2294591203786
15 | 3312782
16 |
17 | -
18 | 5436843
19 | 48668457
20 | 2294591203786
21 | 3312782
22 |
23 | -
24 | 7695515
25 | 63962088
26 | 2294591203786
27 | 3312782
28 |
29 | -
30 | 14605031
31 | 72549008
32 | 2294591203786
33 | 3312782
34 |
35 |
36 |
37 | -
38 | Intel(R) Core(TM) i7-2600 CPU @ 3.40GHz
39 | 3392
40 | 4
41 | 8
42 |
43 |
44 |
45 | -
46 | 2031
47 | 0
48 |
49 |
50 |
51 | -
52 | 4294967296
53 |
54 | -
55 | 4294967296
56 |
57 |
58 |
59 | -
60 | 11640
61 |
62 |
63 |
64 | -
65 | 1526
66 |
67 |
68 |
69 | -
70 | 6.3.9600
71 | null
72 | Microsoft Windows 8.1 Enterprise
73 |
74 |
75 |
76 | -
77 | 96BFA00A-46E3-4F7E-9169-6F39485BAC52
78 |
79 |
80 |
81 | -
82 | 4
83 | 0
84 | 100000
85 |
86 |
87 |
88 | -
89 | 512
90 | 1048576
91 | true
92 | 20
93 |
94 |
95 |
96 |
--------------------------------------------------------------------------------
/src/EnhancedMonitoring/Logging/EventLogWriter.cs:
--------------------------------------------------------------------------------
1 | //The MIT License (MIT)
2 | //
3 | //Copyright 2015 Microsoft Corporation
4 | //
5 | //Permission is hereby granted, free of charge, to any person obtaining a copy
6 | //of this software and associated documentation files (the "Software"), to deal
7 | //in the Software without restriction, including without limitation the rights
8 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | //copies of the Software, and to permit persons to whom the Software is
10 | //furnished to do so, subject to the following conditions:
11 | //
12 | //The above copyright notice and this permission notice shall be included in
13 | //all copies or substantial portions of the Software.
14 | //
15 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | //THE SOFTWARE.
22 | //
23 | using System;
24 | using System.Collections.Generic;
25 | using System.Diagnostics;
26 | using System.Linq;
27 | using System.Text;
28 | using System.Threading.Tasks;
29 |
30 | namespace EnhancedMonitoring.Logging
31 | {
32 | public class EventLogWriter : LogWriter
33 | {
34 | public const String LogName = "Enhanced Monitoring";
35 | public const String Source = "Enhanced Monitoring Provider Service";
36 | public const String EventLogMsgFormat = "There are {0} error(s), {1} warning(s) during the last {2} minute(s). "
37 | + "For more information please view the log file, \"{3}\".";
38 | public const double DefaultLogInterval = 60;
39 |
40 | private int warningCount;
41 | private int errorCount;
42 | private DateTime lastFlush = DateTime.Now;
43 | private double flushIntervalInMinutes;
44 | private String logFilePath;
45 |
46 | public EventLogWriter(Configuration.MonitorConfiguration conf)
47 | {
48 | this.logFilePath = conf.LogFilePath;
49 | this.flushIntervalInMinutes = conf.EventLogInterval <= 0 ? DefaultLogInterval : conf.EventLogInterval;
50 | }
51 |
52 | public void Write(LogLevel level, String msg)
53 | {
54 | switch(level)
55 | {
56 | case LogLevel.Warning:
57 | warningCount++;
58 | break;
59 | case LogLevel.Error:
60 | errorCount++;
61 | break;
62 | default:
63 | break;
64 | }
65 | if(errorCount > 0 || warningCount > 0)
66 | {
67 | DateTime now = DateTime.Now;
68 | if (now.Subtract(this.lastFlush).TotalMinutes > this.flushIntervalInMinutes)
69 | {
70 | WriteEventLog();
71 | this.lastFlush = now;
72 | errorCount = 0;
73 | warningCount = 0;
74 | }
75 | }
76 | }
77 |
78 | protected virtual void WriteEventLog()
79 | {
80 | String msg = String.Format(EventLogMsgFormat, errorCount, warningCount,
81 | this.flushIntervalInMinutes, this.logFilePath);
82 | using (EventLog log = new EventLog(EventLogWriter.LogName))
83 | {
84 | log.Source = EventLogWriter.Source;
85 | log.WriteEntry(msg, this.errorCount > 0 ? EventLogEntryType.Error : EventLogEntryType.Warning);
86 | }
87 | }
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/src/Service/EnhacedMonitoringProvider.cs:
--------------------------------------------------------------------------------
1 | //The MIT License (MIT)
2 | //
3 | //Copyright 2015 Microsoft Corporation
4 | //
5 | //Permission is hereby granted, free of charge, to any person obtaining a copy
6 | //of this software and associated documentation files (the "Software"), to deal
7 | //in the Software without restriction, including without limitation the rights
8 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | //copies of the Software, and to permit persons to whom the Software is
10 | //furnished to do so, subject to the following conditions:
11 | //
12 | //The above copyright notice and this permission notice shall be included in
13 | //all copies or substantial portions of the Software.
14 | //
15 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | //THE SOFTWARE.
22 | //
23 | using EnhancedMonitoring.Configuration;
24 | using EnhancedMonitoring.Logging;
25 | using System;
26 | using System.Collections.Generic;
27 | using System.ComponentModel;
28 | using System.Data;
29 | using System.Diagnostics;
30 | using System.Linq;
31 | using System.ServiceProcess;
32 | using System.Text;
33 | using System.Threading;
34 | using System.Threading.Tasks;
35 |
36 | namespace EnhancedMonitoring.Service
37 | {
38 | public partial class EnhacedMonitoring : ServiceBase
39 | {
40 | private const Int64 MIN_REFRESH_RATE = 60; //Default minimal refresh rate is 60 seconds
41 |
42 | public EnhacedMonitoring()
43 | {
44 | InitializeComponent();
45 | }
46 |
47 | protected override void OnStart(string[] args)
48 | {
49 | var configFilePath = String.Format(@"{0}\{1}\{2}",
50 | System.Environment.GetFolderPath(System.Environment.SpecialFolder.CommonApplicationData),
51 | "Enhanced Monitoring", "EnhancedMonitoringProviderConfig.xml");
52 |
53 | var defaultLogPath = String.Format(@"{0}\{1}\{2}\{3}",
54 | System.Environment.GetFolderPath(System.Environment.SpecialFolder.CommonApplicationData),
55 | "Enhanced Monitoring", "log", "monitor.log");
56 |
57 | MonitorConfiguration conf = MonitorConfiguration.Load(configFilePath);
58 | conf.LogFilePath = conf.LogFilePath ?? defaultLogPath;
59 | Logger.Init(conf);
60 | timer = new Timer(_ => this.RunMonitoringTask(conf), null, 0, Timeout.Infinite);
61 |
62 | Logger.Info("Monitoring service started");
63 | }
64 |
65 | private Timer timer;
66 |
67 | private void RunMonitoringTask(MonitorConfiguration conf)
68 | {
69 | Logger.Info("Start monitoring task");
70 | DateTime start = DateTime.Now;
71 | MonitoringTask task = MonitoringTask.CreateInstance(conf);
72 | task.Run();
73 | Logger.Info("Monitoring task finished");
74 | TimeSpan elapsed = DateTime.Now.Subtract(start);
75 | //Substract elapsed time to get the task running exaclty aliging to refresh rate.
76 | long interval = Math.Max(conf.RefreshRate, MIN_REFRESH_RATE) * 1000;
77 | long timeToWait = interval - (long)elapsed.TotalMilliseconds % interval;
78 | //Trigger next task
79 | timer.Change(timeToWait, Timeout.Infinite);
80 | }
81 |
82 | protected override void OnStop()
83 | {
84 | if(this.timer != null)
85 | {
86 | this.timer.Dispose();
87 | }
88 | }
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/src/UnitTest/EventLogTest.cs:
--------------------------------------------------------------------------------
1 | //The MIT License (MIT)
2 | //
3 | //Copyright 2015 Microsoft Corporation
4 | //
5 | //Permission is hereby granted, free of charge, to any person obtaining a copy
6 | //of this software and associated documentation files (the "Software"), to deal
7 | //in the Software without restriction, including without limitation the rights
8 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | //copies of the Software, and to permit persons to whom the Software is
10 | //furnished to do so, subject to the following conditions:
11 | //
12 | //The above copyright notice and this permission notice shall be included in
13 | //all copies or substantial portions of the Software.
14 | //
15 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | //THE SOFTWARE.
22 | //
23 | using System;
24 | using Microsoft.VisualStudio.TestTools.UnitTesting;
25 | using System.Diagnostics;
26 | using EnhancedMonitoring.Logging;
27 | using System.Threading;
28 | using EnhancedMonitoring.Configuration;
29 |
30 | namespace UnitTest
31 | {
32 | [TestClass]
33 | public class EventLogTest
34 | {
35 | public void TestCreateEventLogSource()
36 | {
37 | EventLog.CreateEventSource(new EventSourceCreationData(EventLogWriter.Source, EventLogWriter.LogName)
38 | {
39 | MachineName = System.Environment.MachineName
40 | });
41 | }
42 |
43 | public void TestRemoveEventLogSource()
44 | {
45 | EventLog.DeleteEventSource(EventLogWriter.Source);
46 | }
47 |
48 | //[TestMethod]
49 | public void TestEventLogSource()
50 | {
51 | Assert.IsTrue(EventLog.Exists(EventLogWriter.LogName));
52 | //Assert.IsTrue(EventLog.SourceExists(EventLogWriter.Source));
53 |
54 | using (EventLog log = new EventLog())
55 | {
56 | log.Log = EventLogWriter.LogName;
57 | log.Source = EventLogWriter.Source;
58 | log.MachineName = System.Environment.MachineName;
59 | log.WriteEntry("Test", EventLogEntryType.Warning);
60 | }
61 | }
62 |
63 | [TestMethod]
64 | public void TestEventLogFlushInterval()
65 | {
66 | var writer = new ShimEventLogWriter(new MonitorConfiguration()
67 | {
68 | EventLogInterval = 100.0 / 60000 //100ms
69 | });
70 |
71 | //Try to refresh timestamp for last flush.
72 | //A flush will be triggered if required.
73 | //And the timestamp will be reset to NOW
74 | writer.Write(LogLevel.Error, "");
75 |
76 | //Clear flushed flag and write a log record.
77 | writer.Flushed = false;
78 | writer.Write(LogLevel.Info, "");
79 | Assert.IsFalse(writer.Flushed);
80 |
81 | //Clear flushed flag and wait for 120ms
82 | writer.Flushed = false;
83 | Thread.Sleep(120);
84 |
85 | //Trigger a flush and check the flag.
86 | writer.Write(LogLevel.Info, "");
87 | Assert.IsTrue(writer.Flushed);
88 | }
89 | }
90 |
91 | class ShimEventLogWriter:EventLogWriter
92 | {
93 |
94 | public ShimEventLogWriter(MonitorConfiguration conf) : base(conf) { }
95 |
96 | public bool Flushed { get; set; }
97 | protected override void WriteEventLog()
98 | {
99 | this.Flushed = true;
100 | }
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/src/UnitTest/LoggerTest.cs:
--------------------------------------------------------------------------------
1 | //The MIT License (MIT)
2 | //
3 | //Copyright 2015 Microsoft Corporation
4 | //
5 | //Permission is hereby granted, free of charge, to any person obtaining a copy
6 | //of this software and associated documentation files (the "Software"), to deal
7 | //in the Software without restriction, including without limitation the rights
8 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | //copies of the Software, and to permit persons to whom the Software is
10 | //furnished to do so, subject to the following conditions:
11 | //
12 | //The above copyright notice and this permission notice shall be included in
13 | //all copies or substantial portions of the Software.
14 | //
15 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | //THE SOFTWARE.
22 | //
23 | using EnhancedMonitoring.Logging;
24 | using EnhancedMonitoring.Configuration;
25 | using System;
26 | using System.Text;
27 | using System.Collections.Generic;
28 | using Microsoft.VisualStudio.TestTools.UnitTesting;
29 |
30 | namespace UnitTest
31 | {
32 | ///
33 | /// Summary description for LoggerTest
34 | ///
35 | [TestClass]
36 | public class LoggerTest
37 | {
38 | [TestMethod]
39 | public void TestLog()
40 | {
41 | var conf = new MonitorConfiguration()
42 | {
43 | LogLevel = "Info"
44 | };
45 | var logWriter = new TestLogWriter();
46 | Logger.Init(conf, new LogWriter[] { logWriter });
47 |
48 | Logger.Verbose("Trival");
49 | Assert.IsNull(logWriter.Msg);
50 |
51 | Logger.Info("Formated information: {0}", "Nothing");
52 | Assert.IsTrue(logWriter.Msg.Contains("Formated information"));
53 | Assert.AreEqual(LogLevel.Info, logWriter.Level);
54 | Console.WriteLine(logWriter.Msg);
55 |
56 | try
57 | {
58 | RaiseException();
59 | }
60 | catch(Exception e)
61 | {
62 | Logger.Error(e);
63 | //Check call stack is logged.
64 | Assert.IsTrue(logWriter.Msg.Contains("at UnitTest.LoggerTest.TestLog()"));
65 | Console.WriteLine(logWriter.Msg);
66 | }
67 | }
68 |
69 | [TestMethod]
70 | public void TestLogLevelConfigure()
71 | {
72 | var conf = new MonitorConfiguration()
73 | {
74 | LogLevel = "Infoasdfasdf"
75 | };
76 | var logWriter = new TestLogWriter();
77 | Logger.Init(conf, new LogWriter[] { logWriter });
78 | Logger.Info("Test");
79 | Assert.AreEqual(LogLevel.Info, logWriter.Level);
80 | }
81 |
82 | [TestMethod]
83 | public void TestZeroLogWriter()
84 | {
85 | var conf = new MonitorConfiguration()
86 | {
87 | LogLevel = "Infoasdfasdf"
88 | };
89 |
90 | Logger.Init(conf, new LogWriter[0]);
91 | Logger.Info("Test");
92 | }
93 |
94 | private void RaiseException()
95 | {
96 | throw new NotImplementedException();
97 | }
98 | }
99 |
100 | class TestLogWriter : LogWriter
101 | {
102 | public LogLevel Level { get; set; }
103 | public String Msg { get; set; }
104 |
105 | public void Write(LogLevel level, String msg)
106 | {
107 | this.Level = level;
108 | this.Msg = msg;
109 | }
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/src/UnitTest/JSONHelper.cs:
--------------------------------------------------------------------------------
1 | //The MIT License (MIT)
2 | //
3 | //Copyright 2015 Microsoft Corporation
4 | //
5 | //Permission is hereby granted, free of charge, to any person obtaining a copy
6 | //of this software and associated documentation files (the "Software"), to deal
7 | //in the Software without restriction, including without limitation the rights
8 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | //copies of the Software, and to permit persons to whom the Software is
10 | //furnished to do so, subject to the following conditions:
11 | //
12 | //The above copyright notice and this permission notice shall be included in
13 | //all copies or substantial portions of the Software.
14 | //
15 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | //THE SOFTWARE.
22 | //
23 | using System;
24 | using System.Collections.Generic;
25 | using System.Linq;
26 | using System.Text;
27 | using System.Threading.Tasks;
28 |
29 | namespace UnitTest
30 | {
31 |
32 | class JsonHelper
33 | {
34 | private const string INDENT_STRING = " ";
35 | public static string FormatJson(string str)
36 | {
37 | var indent = 0;
38 | var quoted = false;
39 | var sb = new StringBuilder();
40 | for (var i = 0; i < str.Length; i++)
41 | {
42 | var ch = str[i];
43 | switch (ch)
44 | {
45 | case '{':
46 | case '[':
47 | sb.Append(ch);
48 | if (!quoted)
49 | {
50 | sb.AppendLine();
51 | Enumerable.Range(0, ++indent).ForEach(item => sb.Append(INDENT_STRING));
52 | }
53 | break;
54 | case '}':
55 | case ']':
56 | if (!quoted)
57 | {
58 | sb.AppendLine();
59 | Enumerable.Range(0, --indent).ForEach(item => sb.Append(INDENT_STRING));
60 | }
61 | sb.Append(ch);
62 | break;
63 | case '"':
64 | sb.Append(ch);
65 | bool escaped = false;
66 | var index = i;
67 | while (index > 0 && str[--index] == '\\')
68 | escaped = !escaped;
69 | if (!escaped)
70 | quoted = !quoted;
71 | break;
72 | case ',':
73 | sb.Append(ch);
74 | if (!quoted)
75 | {
76 | sb.AppendLine();
77 | Enumerable.Range(0, indent).ForEach(item => sb.Append(INDENT_STRING));
78 | }
79 | break;
80 | case ':':
81 | sb.Append(ch);
82 | if (!quoted)
83 | sb.Append(" ");
84 | break;
85 | default:
86 | sb.Append(ch);
87 | break;
88 | }
89 | }
90 | return sb.ToString();
91 | }
92 | }
93 |
94 | static class Extensions
95 | {
96 | public static void ForEach(this IEnumerable ie, Action action)
97 | {
98 | foreach (var i in ie)
99 | {
100 | action(i);
101 | }
102 | }
103 | }
104 | }
105 |
--------------------------------------------------------------------------------
/src/EnhancedMonitoring/Logging/FileLogWriter.cs:
--------------------------------------------------------------------------------
1 | //The MIT License (MIT)
2 | //
3 | //Copyright 2015 Microsoft Corporation
4 | //
5 | //Permission is hereby granted, free of charge, to any person obtaining a copy
6 | //of this software and associated documentation files (the "Software"), to deal
7 | //in the Software without restriction, including without limitation the rights
8 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | //copies of the Software, and to permit persons to whom the Software is
10 | //furnished to do so, subject to the following conditions:
11 | //
12 | //The above copyright notice and this permission notice shall be included in
13 | //all copies or substantial portions of the Software.
14 | //
15 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | //THE SOFTWARE.
22 | //
23 | using System;
24 | using System.Collections.Generic;
25 | using System.IO;
26 | using System.Linq;
27 | using System.Text;
28 | using System.Threading;
29 | using System.Threading.Tasks;
30 |
31 | namespace EnhancedMonitoring.Logging
32 | {
33 | public class FileLogWriter : LogWriter
34 | {
35 | public const Int64 DefaultLogFileSize = 4 * 1024 * 1024;
36 | public const Int32 DefaultLogRetention = 10;
37 |
38 | private String filePath;
39 | private Int64 logFileSize;
40 | private Int32 maxLogRetention;
41 | private Object writeLock = new Object();
42 |
43 | public FileLogWriter(Configuration.MonitorConfiguration conf)
44 | {
45 | this.filePath = conf.LogFilePath;
46 | this.logFileSize = conf.LogFileSize <= 0 ? DefaultLogFileSize : conf.LogFileSize;
47 | this.maxLogRetention = conf.MaxLogRetention <= 0 ? DefaultLogRetention : conf.MaxLogRetention;
48 | Directory.CreateDirectory(Path.GetDirectoryName(this.filePath));
49 | }
50 |
51 | public void Write(LogLevel level, String msg)
52 | {
53 | lock(writeLock)
54 | {
55 | FileInfo file = new FileInfo(this.filePath);
56 | if (file.Exists && file.Length > this.logFileSize)
57 | {
58 | RotateLogFile();
59 | }
60 | File.AppendAllLines(this.filePath, new String[] { msg }, Encoding.UTF8);
61 | }
62 | }
63 |
64 | ///
65 | ///
66 | /// Rotate the old log to another file. The rule is:
67 | /// 1. log -> log.0
68 | /// 2. log.$(i) -> log.$(i + 1)
69 | /// 3. IF i + 1 == LogRetention: delete log.$(i)
70 | ///
71 | ///
72 | protected void RotateLogFile()
73 | {
74 | int index = 0;
75 | String rotateFilePath = GetRotateFilePath(index);
76 | while(File.Exists(rotateFilePath))
77 | {
78 | //Reaches retention limit, delete the oldest log
79 | if (index == this.maxLogRetention - 1)
80 | {
81 | File.Delete(rotateFilePath);
82 | break;
83 | }
84 | index++;
85 | rotateFilePath = GetRotateFilePath(index);
86 | }
87 |
88 | for(int i = index; i > 0; i--)
89 | {
90 | String src = GetRotateFilePath(i - 1);
91 | String dest = GetRotateFilePath(i);
92 | File.Move(src, dest);
93 | }
94 | rotateFilePath = String.Format("{0}.{1}", this.filePath, 0);
95 | File.Move(this.filePath, rotateFilePath);
96 | }
97 |
98 | private String GetRotateFilePath(int index)
99 | {
100 | return String.Format("{0}.{1}", this.filePath, index);
101 | }
102 | }
103 | }
104 |
--------------------------------------------------------------------------------
/src/UnitTest/NamedArgumentHelperTest.cs:
--------------------------------------------------------------------------------
1 | //The MIT License (MIT)
2 | //
3 | //Copyright 2015 Microsoft Corporation
4 | //
5 | //Permission is hereby granted, free of charge, to any person obtaining a copy
6 | //of this software and associated documentation files (the "Software"), to deal
7 | //in the Software without restriction, including without limitation the rights
8 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | //copies of the Software, and to permit persons to whom the Software is
10 | //furnished to do so, subject to the following conditions:
11 | //
12 | //The above copyright notice and this permission notice shall be included in
13 | //all copies or substantial portions of the Software.
14 | //
15 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | //THE SOFTWARE.
22 | //
23 | using System;
24 | using Microsoft.VisualStudio.TestTools.UnitTesting;
25 | using System.Collections.Generic;
26 | using EnhancedMonitoring;
27 | using EnhancedMonitoring.Configuration;
28 |
29 | namespace UnitTest
30 | {
31 | [TestClass]
32 | public class NamedArgumentHelperTest
33 | {
34 | [TestMethod]
35 | public void TestResolveNamedArgument()
36 | {
37 | var str = "MaxClockSpeed_{0}_{1}";
38 | var expected = "MaxClockSpeed_ubuntu_0";
39 | var argsName = new List(){
40 | new WhereArgConfiguration(){ Name ="VirtualMachine"},
41 | new WhereArgConfiguration(){Name = "ProcessorId" }
42 | };
43 | var args = new Dictionary()
44 | {
45 | {"VirtualMachine", "ubuntu"},
46 | {"ProcessorId", 0}
47 | };
48 |
49 | Assert.AreEqual(expected, NamedArgumentHelper.Resolve(str, argsName, args));
50 | }
51 |
52 | [TestMethod]
53 | public void TestResolveNamedArgumentNagativeCase()
54 | {
55 | var str = "MaxClockSpeed_{0}_{1}";
56 | var argsName = new List(){
57 | new WhereArgConfiguration(){ Name ="VirtualMachine"},
58 | new WhereArgConfiguration(){Name = "ProcessorId" }
59 | };
60 | var args = new Dictionary(){ {"VirtualMachine", "ubuntu"}};
61 |
62 | //Argument name is null
63 | try
64 | {
65 | NamedArgumentHelper.Resolve(str, null, args);
66 | Assert.Fail("FormatException is expected");
67 | }
68 | catch (ArgumentException e)
69 | {
70 | Console.WriteLine(e);
71 | }
72 |
73 | //Argument names are less than cells
74 | try
75 | {
76 | NamedArgumentHelper.Resolve(str, new List() {
77 | new WhereArgConfiguration(){Name = "VirtualMachine"} }, args);
78 | Assert.Fail("FormatException is expected");
79 | }
80 | catch (ArgumentException e)
81 | {
82 | Console.WriteLine(e);
83 | }
84 |
85 | //Name argument map is null
86 | try
87 | {
88 | NamedArgumentHelper.Resolve(str, argsName, null);
89 | Assert.Fail("ArgumentException is expected");
90 | }
91 | catch (ArgumentException e)
92 | {
93 | Console.WriteLine(e);
94 | }
95 |
96 | //Named argument not found
97 | try
98 | {
99 | NamedArgumentHelper.Resolve(str, argsName, args);
100 | Assert.Fail("ArgumentException is expected");
101 | }
102 | catch (ArgumentException e)
103 | {
104 | Console.WriteLine(e);
105 | }
106 | }
107 | }
108 | }
109 |
--------------------------------------------------------------------------------
/src/EnhancedMonitoring/SupportedVMDetector.cs:
--------------------------------------------------------------------------------
1 | //The MIT License (MIT)
2 | //
3 | //Copyright 2015 Microsoft Corporation
4 | //
5 | //Permission is hereby granted, free of charge, to any person obtaining a copy
6 | //of this software and associated documentation files (the "Software"), to deal
7 | //in the Software without restriction, including without limitation the rights
8 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | //copies of the Software, and to permit persons to whom the Software is
10 | //furnished to do so, subject to the following conditions:
11 | //
12 | //The above copyright notice and this permission notice shall be included in
13 | //all copies or substantial portions of the Software.
14 | //
15 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | //THE SOFTWARE.
22 | //
23 | using EnhancedMonitoring.Configuration;
24 | using EnhancedMonitoring.Logging;
25 | using System;
26 | using System.Collections.Generic;
27 | using System.Linq;
28 | using System.Management;
29 | using System.Text;
30 | using System.Threading.Tasks;
31 | using System.Xml;
32 |
33 | namespace EnhancedMonitoring
34 | {
35 | public class SupportedVMDetector
36 | {
37 | protected const String WMI_Namespace = @"root\virtualization\v2";
38 | protected const String WMI_Class_Msvm_ComputerSystem = @"Msvm_ComputerSystem";
39 | protected const String WMI_Class_Msvm_KvpExchangeComponent = @"Msvm_KvpExchangeComponent";
40 |
41 | public static SupportedVMDetector CreateInstance(SupportedVMDetectorConfiguration conf)
42 | {
43 | return new SupportedVMDetector(conf);
44 | }
45 |
46 | private String SupportedVMKey;
47 | public SupportedVMDetector(SupportedVMDetectorConfiguration conf)
48 | {
49 | this.SupportedVMKey = conf.GuestDataItemKey;
50 | }
51 |
52 | public IList> GetSupportedVM()
53 | {
54 | using (var vms = WMIHelper.QueryInstacnes(WMI_Namespace, WMI_Class_Msvm_ComputerSystem, "EnabledState = 2 and Caption='Virtual Machine'"))
55 | {
56 | var tasks = new List>>();
57 | foreach(var vm in vms.Cast())
58 | {
59 | tasks.Add(Task.Run>(() =>
60 | {
61 | var objs = vm.GetRelated(WMI_Class_Msvm_KvpExchangeComponent);
62 | foreach (var obj in objs)
63 | {
64 | var kvps = obj.Properties["GuestExchangeItems"].Value as String[];
65 |
66 | if (kvps.Any(kvp => kvp.IndexOf(this.SupportedVMKey) >= 0))
67 | {
68 | var vmdata = new Dictionary();
69 | vmdata.Add("VirtualMachineName", vm.Properties["Name"].Value);
70 | vmdata.Add("VirtualMachineElementName", vm.Properties["ElementName"].Value);
71 | vmdata.Add("VirtualMachinePath", vm.Path);
72 | vmdata.Add("GuestExchangeItems", kvps);
73 | return vmdata;
74 | }
75 | }
76 | return null;
77 | }));
78 | }
79 | try
80 | {
81 | var task = Task.WhenAll>(tasks);
82 | task.Wait();
83 | return task.Result.Where(x => x != null).ToList();
84 | }
85 | catch(AggregateException e)
86 | {
87 | foreach(var inner in e.InnerExceptions)
88 | {
89 | Logger.Error(inner);
90 | throw inner;
91 | }
92 | throw;
93 | }
94 | }
95 | }
96 |
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/src/UnitTest/SampleMonitor.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
27 |
28 |
29 |
30 |
31 | 60
32 |
33 |
34 | 1.0.0
35 |
36 |
37 | Enhanced_Monitoring_Metric_Data_Item_Part_
38 |
39 |
40 | 700
41 |
42 |
43 |
44 | 10
45 |
46 |
47 |
48 | 4194304
49 |
50 |
51 | c:\ProgramData\Enhanced Monitoring\log
52 |
53 |
54 | true
55 | 200
56 |
57 |
58 |
59 |
60 |
61 |
62 | Enhanced_Monitoring_Supported
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 | VirtualMachineStatus
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 | root\cimv2
85 |
86 |
87 |
88 | WIN32_PerfRawData_HvStats_HyperVHypervisorVirtualProcessor
89 |
90 |
91 |
92 | Name like "%%{0}%%"
93 |
94 |
95 |
96 |
97 |
98 | VirtualMachineElementName
99 |
100 |
101 |
102 |
103 |
104 |
105 | VirtualProcessor_PercentHypervisorRuntime
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
--------------------------------------------------------------------------------
/src/UnitTest/FormatHelperTest.cs:
--------------------------------------------------------------------------------
1 | //The MIT License (MIT)
2 | //
3 | //Copyright 2015 Microsoft Corporation
4 | //
5 | //Permission is hereby granted, free of charge, to any person obtaining a copy
6 | //of this software and associated documentation files (the "Software"), to deal
7 | //in the Software without restriction, including without limitation the rights
8 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | //copies of the Software, and to permit persons to whom the Software is
10 | //furnished to do so, subject to the following conditions:
11 | //
12 | //The above copyright notice and this permission notice shall be included in
13 | //all copies or substantial portions of the Software.
14 | //
15 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | //THE SOFTWARE.
22 | //
23 | using System;
24 | using Microsoft.VisualStudio.TestTools.UnitTesting;
25 | using System.Collections.Generic;
26 | using EnhancedMonitoring.DataFormat;
27 | using System.Runtime.Serialization;
28 |
29 | namespace UnitTest
30 | {
31 | [TestClass]
32 | public class FormatHelperTest
33 | {
34 | [TestMethod]
35 | public void TestToXml()
36 | {
37 | String expected = System.IO.File.ReadAllText(@"..\..\TestToXmlExpectedOutput.xml");
38 | var data = new Dictionary();
39 | data.Add("Name", "Dictionary(JSON object) to Xml Test");
40 | data.Add("TestCases", new String[]
41 | {
42 | "Case1: String as Field",
43 | "Case2: String Array as Field",
44 | "Case3: Dictionary as Field",
45 | "Case4: Object Array as Field",
46 | "Case5: Null"
47 | });
48 | data.Add("ExpectedBehavior", new Dictionary() {
49 | {"ForAll", "Key name as XElement name "},
50 | {"Case1", "String content as XElement content"},
51 | {"Case2", "Each element becomes a child XElement with name 'Item'"},
52 | {"Case3", "Dictionary becomes a child XElement"},
53 | {"Case4", new String[]
54 | {
55 | "1. Each element in the array is a dictionary",
56 | "2. The 1st dictionary itself contains an array field",
57 | "3. The 2nd dictionary itself contains a dictionary"
58 | }
59 | },
60 | {"Case5", "Output 'null'"}
61 | });
62 | data.Add("ObjectArray", new Dictionary[] {
63 | new Dictionary()
64 | {
65 | {"ArrayObject", new String[]{"Element 1", "Element 1"}}
66 | },
67 | new Dictionary()
68 | {
69 | {
70 | "DictionaryObject", new Dictionary()
71 | {
72 | {"ObjectField", "ObjectValue"}
73 | }
74 | }
75 | },
76 | });
77 | data.Add("HandleNull", null);
78 |
79 | var xmlStr = DataFormatHelper.ToXml(data);
80 | Console.WriteLine(xmlStr);
81 | Assert.AreEqual(expected, xmlStr);
82 | }
83 |
84 | [TestMethod]
85 | public void TestToXmlNegative()
86 | {
87 | var data = new Dictionary();
88 | data.Add("", null);
89 | try
90 | {
91 | DataFormatHelper.ToXml(data);
92 | }
93 | catch (ArgumentException e)
94 | {
95 | Assert.AreEqual("Node name can't be null or empty.", e.Message);
96 | }
97 |
98 | data.Clear();
99 | data.Add("Node Name with Space", "Space will be replaced with _");
100 | var xmlStr = DataFormatHelper.ToXml(data);
101 | String expected =
102 | @"
103 | Space will be replaced with _
104 | ";
105 | Assert.AreEqual(expected, xmlStr);
106 | }
107 | }
108 |
109 | }
110 |
--------------------------------------------------------------------------------
/packages/MSI/EnhancedMonitoring/Setup.wixproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | x64
6 | 3.8
7 | a6aa397b-1031-4fbf-9a8a-b50ee7318ec6
8 | 2.0
9 | Debug.EnhancedMonitoring
10 | Package
11 | $(MSBuildExtensionsPath32)\Microsoft\WiX\v3.x\Wix.targets
12 | $(MSBuildExtensionsPath)\Microsoft\WiX\v3.x\Wix.targets
13 |
14 |
15 | bin\$(Configuration)\
16 | obj\$(Configuration)\
17 | Debug
18 |
19 |
20 | bin\$(Configuration)\
21 | obj\$(Configuration)\
22 |
23 |
24 | Debug
25 | bin\$(Platform)\$(Configuration)\
26 | obj\$(Platform)\$(Configuration)\
27 |
28 |
29 | bin\$(Platform)\$(Configuration)\
30 | obj\$(Platform)\$(Configuration)\
31 |
32 |
33 | bin\$(Platform)\$(Configuration)\
34 | obj\$(Platform)\$(Configuration)\
35 |
36 |
37 | Debug
38 | bin\$(Platform)\$(Configuration)\
39 | obj\$(Platform)\$(Configuration)\
40 |
41 |
42 | bin\$(Platform)\$(Configuration)\
43 | obj\$(Platform)\$(Configuration)\
44 |
45 |
46 | Debug
47 | bin\$(Platform)\$(Configuration)\
48 | obj\$(Platform)\$(Configuration)\
49 |
50 |
51 |
52 | $(WixExtDir)\WixUIExtension.dll
53 | WixUIExtension
54 |
55 |
56 | $(WixExtDir)\WixUtilExtension.dll
57 | WixUtilExtension
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 | EnhancedMonitoring
66 | {7eacc378-2947-4f2e-ab0f-eb57be7d3680}
67 | True
68 | True
69 | Binaries;Content;Satellites
70 | INSTALLFOLDER
71 |
72 |
73 | Service
74 | {ed1f3b96-683f-4d16-b4f9-06765e3697c1}
75 | True
76 | True
77 | Binaries;Content;Satellites
78 | INSTALLFOLDER
79 |
80 |
81 |
82 |
90 |
--------------------------------------------------------------------------------
/src/UnitTest/KVPWriterTest.cs:
--------------------------------------------------------------------------------
1 | //The MIT License (MIT)
2 | //
3 | //Copyright 2015 Microsoft Corporation
4 | //
5 | //Permission is hereby granted, free of charge, to any person obtaining a copy
6 | //of this software and associated documentation files (the "Software"), to deal
7 | //in the Software without restriction, including without limitation the rights
8 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | //copies of the Software, and to permit persons to whom the Software is
10 | //furnished to do so, subject to the following conditions:
11 | //
12 | //The above copyright notice and this permission notice shall be included in
13 | //all copies or substantial portions of the Software.
14 | //
15 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | //THE SOFTWARE.
22 | //
23 | using System;
24 | using System.Linq;
25 | using Microsoft.VisualStudio.TestTools.UnitTesting;
26 | using System.Collections.Generic;
27 | using EnhancedMonitoring;
28 | using System.Management;
29 | using EnhancedMonitoring.Configuration;
30 |
31 | namespace UnitTest
32 | {
33 | [TestClass]
34 | public class KVPWriterTest
35 | {
36 |
37 | private const String testKey = "TestKVPWriterKey1";
38 | private const String testKey2 = "TestKVPWriterKey2";
39 |
40 | //[TestMethod]
41 | public void TestOverloadKVP()
42 | {
43 | var vm = WMIHelper.QueryFirstInstacne(@"root\virtualization\v2", "Msvm_ComputerSystem ", "enabledstate = 2 and caption = 'Virtual Machine'");
44 | Assert.IsNotNull(vm);
45 |
46 | var writer = KeyValuePairWriter.CreateInstance(new KvpConfiguration());
47 | var data = new Dictionary();
48 |
49 | var chars = new char[1000];
50 | for(int i = 0; i < chars.Length; i++)
51 | {
52 | chars[i] = 'a';
53 | }
54 | var val = new String(chars);
55 | for (int i = 0; i < 1000; i++ )
56 | {
57 | data.Clear();
58 | for (int j = 0; j < 10; j++)
59 | {
60 | data.Add(String.Format("TestKVP_{0}", j), val);
61 | }
62 |
63 | var args = new Dictionary() {
64 | {"VirtualMachinePath", vm.Path.ToString()},
65 | {"VirtualMachineName", vm.Properties["Name"].Value},
66 | };
67 |
68 | writer.Remove(args, data);
69 | writer.Write(args, data);
70 | }
71 | vm.Dispose();
72 | }
73 |
74 | [TestMethod]
75 | public void TestWriteKVP()
76 | {
77 |
78 | var vm = WMIHelper.QueryFirstInstacne(@"root\virtualization\v2", "Msvm_ComputerSystem ", "enabledstate = 2 and caption = 'Virtual Machine'");
79 | Assert.IsNotNull(vm);
80 |
81 | var writer = KeyValuePairWriter.CreateInstance(new KvpConfiguration());
82 | var data = new Dictionary();
83 | data.Add(testKey, DateTime.Now.ToString());
84 | data.Add(testKey2, DateTime.Now.ToString());
85 |
86 | var args = new Dictionary() {
87 | {"VirtualMachinePath", vm.Path.ToString()},
88 | {"VirtualMachineName", vm.Properties["Name"].Value},
89 | };
90 |
91 | writer.Remove(args, data);
92 | writer.Write(args, data);
93 |
94 | vm.Dispose();
95 | }
96 |
97 | //Uncomment the following line to cleanup kvp
98 | //[TestMethod]
99 | public void CleanupKVP()
100 | {
101 | using (var vm = WMIHelper.QueryFirstInstacne(@"root\virtualization\v2", "Msvm_ComputerSystem ", "enabledstate = 2 and caption = 'Virtual Machine'"))
102 | {
103 | Assert.IsNotNull(vm);
104 | Console.WriteLine("Clean up kvp for: " + vm.Properties["ElementName"].Value);
105 | var writer = KeyValuePairWriter.CreateInstance(new KvpConfiguration());
106 |
107 | var NULL = new Object();
108 |
109 | var data = new Dictionary();
110 | data.Add(testKey, NULL);
111 | data.Add(testKey2, NULL);
112 |
113 | var args = new Dictionary()
114 | {
115 | {"VirtualMachinePath", vm.Path.ToString()},
116 | {"VirtualMachineName", vm.Properties["Name"].Value},
117 | };
118 |
119 | writer.Remove(args, data);
120 |
121 | data.Clear();
122 | for (int i = 0; i < 50; i++)
123 | {
124 | data.Add("Enhanced_Monitoring_Metric_Data_Item_Part_" + i, NULL);
125 | }
126 | writer.Remove(args, data);
127 | }
128 |
129 | }
130 | }
131 | }
132 |
--------------------------------------------------------------------------------
/src/EnhancedMonitoring/Logging/Logger.cs:
--------------------------------------------------------------------------------
1 | //The MIT License (MIT)
2 | //
3 | //Copyright 2015 Microsoft Corporation
4 | //
5 | //Permission is hereby granted, free of charge, to any person obtaining a copy
6 | //of this software and associated documentation files (the "Software"), to deal
7 | //in the Software without restriction, including without limitation the rights
8 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | //copies of the Software, and to permit persons to whom the Software is
10 | //furnished to do so, subject to the following conditions:
11 | //
12 | //The above copyright notice and this permission notice shall be included in
13 | //all copies or substantial portions of the Software.
14 | //
15 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | //THE SOFTWARE.
22 | //
23 | using EnhancedMonitoring.Configuration;
24 | using System;
25 | using System.Collections.Generic;
26 | using System.Diagnostics;
27 | using System.Linq;
28 | using System.Text;
29 | using System.Threading.Tasks;
30 |
31 | namespace EnhancedMonitoring.Logging
32 | {
33 | public class Logger
34 | {
35 | private static Object instanceLock = new Object();
36 | private static Logger instance = null;
37 | private const String DateFormat = "yyyy-MM-dd hh:mm:ss.fff";
38 | public static Logger Instance
39 | {
40 | get
41 | {
42 | lock(instanceLock)
43 | {
44 | if (instance == null)
45 | {
46 | throw new NullReferenceException("Log hasn't been initialized");
47 | }
48 | }
49 | return instance;
50 | }
51 | }
52 |
53 | public static void Init(MonitorConfiguration conf)
54 | {
55 | Init(conf, new LogWriter[]
56 | {
57 | new FileLogWriter(conf),
58 | new EventLogWriter(conf)
59 | });
60 | }
61 |
62 | public static void Init(MonitorConfiguration conf, IList writers)
63 | {
64 | lock (instanceLock)
65 | {
66 | if (instance == null)
67 | {
68 | instance = new Logger(conf);
69 | instance.AddWriters(writers);
70 | }
71 | }
72 | }
73 |
74 | public static void Verbose(String format, params Object[] args)
75 | {
76 | Logger.Instance.Log(LogLevel.Verbose, format, args);
77 | }
78 |
79 | public static void Verbose(Exception e)
80 | {
81 | Verbose(ExceptionToString(e));
82 | }
83 |
84 | public static void Info(String format, params Object[] args)
85 | {
86 | Logger.Instance.Log(LogLevel.Info, format, args);
87 | }
88 |
89 | public static void Info(Exception e)
90 | {
91 | Info(ExceptionToString(e));
92 | }
93 |
94 | public static void Warn(String format, params Object[] args)
95 | {
96 | Logger.Instance.Log(LogLevel.Warning, format, args);
97 | }
98 |
99 | public static void Warn(Exception e)
100 | {
101 | Warn(ExceptionToString(e));
102 | }
103 |
104 | public static void Error(String format, params Object[] args)
105 | {
106 | Logger.Instance.Log(LogLevel.Error, format, args);
107 | }
108 |
109 | public static void Error(Exception e)
110 | {
111 | Error(ExceptionToString(e));
112 | }
113 |
114 | private static String ExceptionToString(Exception e)
115 | {
116 | return String.Format("{0}\n{1}", e, e.StackTrace);
117 | }
118 |
119 | private LogLevel logLevel = LogLevel.Info;
120 | private List writers = new List();
121 |
122 | private Logger(MonitorConfiguration conf)
123 | {
124 | Enum.TryParse(conf.LogLevel, out this.logLevel);
125 | }
126 |
127 | public void AddWriters(IList writers)
128 | {
129 | this.writers.AddRange(writers);
130 | }
131 |
132 | public void Log(LogLevel level, String format, params Object[] args)
133 | {
134 | if(level < logLevel)
135 | {
136 | return;
137 | }
138 |
139 | String logMsg = format;
140 | if(args != null && args.Count() != 0)
141 | {
142 | logMsg = String.Format(format, args);
143 | }
144 |
145 | String date = DateTime.Now.ToString(DateFormat);
146 | String msg = String.Format("{0} {1}\t{2}", date, level.ToString().ToUpper(), logMsg);
147 | foreach(var writer in writers)
148 | {
149 | writer.Write(level, msg);
150 | }
151 | }
152 | }
153 | }
154 |
--------------------------------------------------------------------------------
/src/Service/Service.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {ED1F3B96-683F-4D16-B4F9-06765E3697C1}
8 | WinExe
9 | Properties
10 | EnhancedMonitoringProvider.Service
11 | EnhancedMonitoringProvider.Service
12 | v4.5
13 | 512
14 |
15 |
16 | AnyCPU
17 | true
18 | full
19 | false
20 | bin\Debug\
21 | DEBUG;TRACE
22 | prompt
23 | 4
24 |
25 |
26 | AnyCPU
27 | pdbonly
28 | true
29 | bin\Release\
30 | TRACE
31 | prompt
32 | 4
33 |
34 |
35 | true
36 | bin\DebugAndRelease\
37 | DEBUG;TRACE
38 | full
39 | AnyCPU
40 | prompt
41 | MinimumRecommendedRules.ruleset
42 | true
43 |
44 |
45 | true
46 | bin\x64\Debug\
47 | DEBUG;TRACE
48 | full
49 | x64
50 | prompt
51 | MinimumRecommendedRules.ruleset
52 | true
53 |
54 |
55 | bin\x64\Release\
56 | TRACE
57 | true
58 | pdbonly
59 | x64
60 | prompt
61 | MinimumRecommendedRules.ruleset
62 | true
63 |
64 |
65 | true
66 | bin\x64\DebugAndRelease\
67 | DEBUG;TRACE
68 | full
69 | x64
70 | prompt
71 | MinimumRecommendedRules.ruleset
72 | true
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 | Component
87 |
88 |
89 | EnhacedMonitoringProvider.cs
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 | EnhacedMonitoringProvider.cs
100 |
101 |
102 |
103 |
104 | {7eacc378-2947-4f2e-ab0f-eb57be7d3680}
105 | EnhancedMonitoring
106 |
107 |
108 |
109 |
116 |
--------------------------------------------------------------------------------
/src/EnhancedMonitoring/DataCollector/DynamicMemoryMgmtObject.cs:
--------------------------------------------------------------------------------
1 | //The MIT License (MIT)
2 | //
3 | //Copyright 2015 Microsoft Corporation
4 | //
5 | //Permission is hereby granted, free of charge, to any person obtaining a copy
6 | //of this software and associated documentation files (the "Software"), to deal
7 | //in the Software without restriction, including without limitation the rights
8 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | //copies of the Software, and to permit persons to whom the Software is
10 | //furnished to do so, subject to the following conditions:
11 | //
12 | //The above copyright notice and this permission notice shall be included in
13 | //all copies or substantial portions of the Software.
14 | //
15 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | //THE SOFTWARE.
22 | //
23 | using EnhancedMonitoring.Configuration;
24 | using System;
25 | using System.Collections.Generic;
26 | using System.Linq;
27 | using System.Management;
28 | using System.Text;
29 |
30 | namespace EnhancedMonitoring.DataCollector
31 | {
32 | public class DynamicMemoryMgmtObject : MgmtObject
33 | {
34 | public const String WMI_Namespace = @"root\virtualization\v2";
35 | public const String WMI_Class_Msvm_ComputerSystem = @"Msvm_ComputerSystem";
36 | public const String WMI_Class_Msvm_VirtualSystemManagementService = @"Msvm_VirtualSystemManagementService";
37 | public const String WMI_Class_Msvm_VirtualSystemSettingData = @"Msvm_VirtualSystemSettingData";
38 | public const String WMI_Method_GetSummaryInformation = @"GetSummaryInformation";
39 |
40 | public const UInt32 RequestedInformation_MemoryUsage = 103;
41 | public const String KeyName_MemoryUsage = "MemoryUsage";
42 | public const UInt32 RequestedInformation_MemoryAvailable = 112;
43 | public const String KeyName_MemoryAvailable = "MemoryAvailable";
44 | public const UInt32 RequestedInformation_AvaiableMemoryBuffer = 113;
45 | public const String KeyName_AvailableMemoryBuffer = "AvailableMemoryBuffer";
46 |
47 |
48 | public DynamicMemoryMgmtObject(MgmtObjectConfiguration conf) : base(conf)
49 | {
50 | }
51 |
52 | public override Object CollectData(IDictionary args)
53 | {
54 | using (var vmMgmt = WMIHelper.GetFirstInstance(WMI_Namespace, WMI_Class_Msvm_VirtualSystemManagementService))
55 | using (var vm = WMIHelper.QueryFirstInstacne(WMI_Namespace, WMI_Class_Msvm_ComputerSystem,
56 | String.Format("Name='{0}'", args["VirtualMachineName"])))
57 | using (var vmSettings = vm.GetRelated(WMI_Class_Msvm_VirtualSystemSettingData))
58 | using (var inParams = vmMgmt.GetMethodParameters(WMI_Method_GetSummaryInformation))
59 | {
60 | String[] settingDataPath = new String[vmSettings.Count];
61 | int i = 0;
62 | foreach (ManagementObject vmSetting in vmSettings)
63 | {
64 | settingDataPath[i++] = vmSetting.Path.Path;
65 | break;
66 | }
67 | var data = new Dictionary()
68 | {
69 | {KeyName_MemoryUsage, null},
70 | {KeyName_MemoryAvailable, null},
71 | {KeyName_AvailableMemoryBuffer, null},
72 | };
73 |
74 | if (settingDataPath.Length != 0)
75 | {
76 | inParams["SettingData"] = settingDataPath;
77 | inParams["RequestedInformation"] = new UInt32[]
78 | {
79 | RequestedInformation_MemoryUsage,
80 | RequestedInformation_MemoryAvailable,
81 | RequestedInformation_AvaiableMemoryBuffer
82 | };
83 |
84 | var outParams = vmMgmt.InvokeMethod(WMI_Method_GetSummaryInformation, inParams, null);
85 | if ((UInt32)outParams["ReturnValue"] == 0)//Completed
86 | {
87 | var summaryInfoList = (ManagementBaseObject[])outParams["SummaryInformation"];
88 | var summaryInfo = summaryInfoList.FirstOrDefault();
89 | data[KeyName_MemoryUsage] = summaryInfo[KeyName_MemoryUsage];
90 | data[KeyName_MemoryAvailable] = summaryInfo[KeyName_MemoryAvailable];
91 | data[KeyName_AvailableMemoryBuffer] = summaryInfo[KeyName_AvailableMemoryBuffer];
92 | }
93 | else
94 | {
95 | throw new ManagementException(String.Format("Method {0} returns error:{1}", WMI_Method_GetSummaryInformation,
96 | (UInt32)outParams["ReturnValue"]));
97 | }
98 | }
99 | return data;
100 | }
101 | }
102 |
103 | public override String KeyName
104 | {
105 | get
106 | {
107 | return this.conf.As ?? "DynamicMemory";
108 | }
109 | }
110 | }
111 | }
112 |
--------------------------------------------------------------------------------
/src/UnitTest/MetricTest.cs:
--------------------------------------------------------------------------------
1 | //The MIT License (MIT)
2 | //
3 | //Copyright 2015 Microsoft Corporation
4 | //
5 | //Permission is hereby granted, free of charge, to any person obtaining a copy
6 | //of this software and associated documentation files (the "Software"), to deal
7 | //in the Software without restriction, including without limitation the rights
8 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | //copies of the Software, and to permit persons to whom the Software is
10 | //furnished to do so, subject to the following conditions:
11 | //
12 | //The above copyright notice and this permission notice shall be included in
13 | //all copies or substantial portions of the Software.
14 | //
15 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | //THE SOFTWARE.
22 | //
23 | using System;
24 | using System.Linq;
25 | using Microsoft.VisualStudio.TestTools.UnitTesting;
26 | using EnhancedMonitoring.Configuration;
27 | using EnhancedMonitoring.DataFormat;
28 | using EnhancedMonitoring.DataCollector;
29 | using EnhancedMonitoring;
30 | using System.Collections.Generic;
31 |
32 | namespace UnitTest
33 | {
34 | [TestClass]
35 | public class MetricTest
36 | {
37 | [TestMethod]
38 | public void TestMetricJSON()
39 | {
40 | MonitorConfiguration conf = MonitorConfiguration.Load(@"..\..\..\EnhancedMonitoring\Configuration\EnhancedMonitoringProviderConfig.xml");
41 | List mgmtObjects = new List();
42 | foreach (var mgmtObjConf in conf.MgmtObjects)
43 | {
44 | mgmtObjects.Add(MgmtObject.CreateInstance(mgmtObjConf));
45 | }
46 |
47 | Assert.AreNotEqual(0, mgmtObjects.Count);
48 |
49 |
50 | var data = new Dictionary();
51 | var vms = SupportedVMDetector.CreateInstance(conf.SupportedVMDetector).GetSupportedVM();
52 | Assert.AreNotEqual(0, vms.Count);
53 |
54 | var vm = vms.FirstOrDefault();
55 |
56 | var args = new Dictionary(vm);
57 |
58 | foreach (var mgmtObj in mgmtObjects)
59 | {
60 | var watch = System.Diagnostics.Stopwatch.StartNew();
61 | try
62 | {
63 | data.Add(mgmtObj.KeyName, mgmtObj.CollectData(args));
64 | }
65 | catch (Exception e)
66 | {
67 | if (!mgmtObj.SuppressError)
68 | {
69 | Console.WriteLine(e);
70 | Console.WriteLine(e.StackTrace);
71 | Assert.Fail(e.Message);
72 | }
73 | data.Add(mgmtObj.KeyName, null);
74 | }
75 | Console.WriteLine(String.Format("{0}\t{1}", watch.ElapsedMilliseconds, mgmtObj.KeyName));
76 | }
77 |
78 | Assert.IsNotNull(data);
79 | Assert.AreNotEqual(0, data.Count);
80 |
81 | var xmlStr = DataFormatHelper.ToXml(data);
82 | Console.WriteLine(xmlStr);
83 |
84 | //var jsonStr = DataFormatHelper.ToJSON(data);
85 |
86 | //var encodedStr = DataFormatHelper.Base64Encode(jsonStr);
87 |
88 | //var dataChunks = DataFormatHelper.PackString(jsonStr, 900);
89 |
90 | //var packedData = DataFormatHelper.ToChunk("", dataChunks);
91 |
92 | //var encodedDataChunks = DataFormatHelper.PackString(encodedStr, 900);
93 |
94 | //var encodedPackedData = DataFormatHelper.ToChunk("", encodedDataChunks);
95 |
96 | //Console.WriteLine(JsonHelper.FormatJson(jsonStr));
97 | //Console.WriteLine(String.Format("Original JSON string length: {0}", jsonStr.Length));
98 | //Console.WriteLine(String.Format("Encoded JSON string length: {0}", encodedStr.Length));
99 | //Console.WriteLine(String.Format("Packed JSON string length: {0}", packedData.Select(d => d.Value.ToString().Length).Sum()));
100 | //Console.WriteLine(String.Format("Packed encoded JSON string length: {0}", encodedPackedData.Select(d => d.Value.ToString().Length).Sum()));
101 |
102 | }
103 |
104 | //[TestMethod]
105 | public void TestWMIPerformanceCache()
106 | {
107 | Console.WriteLine("First time query");
108 | TestMetricJSON();
109 | System.Threading.Thread.Sleep(60 * 1000);
110 | Console.WriteLine("----------------------------------------------------------------------");
111 | Console.WriteLine("Second time query, after 60seconds");
112 | TestMetricJSON();
113 | }
114 |
115 | //[TestMethod]
116 | public void TestWMIPerformanceMultiple()
117 | {
118 | for(int i= 0; i < 10; i++)
119 | {
120 | var watch = System.Diagnostics.Stopwatch.StartNew();
121 | TestMetricJSON();
122 | Console.WriteLine(String.Format("Elapsed: {0}ms \t Total", watch.ElapsedMilliseconds));
123 | Console.WriteLine("----------------------------------------------------------------------");
124 | }
125 | }
126 | }
127 | }
128 |
--------------------------------------------------------------------------------
/src/EnhancedMonitoring/EnhancedMonitoring.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Debug
6 | AnyCPU
7 | {7EACC378-2947-4F2E-AB0F-EB57BE7D3680}
8 | Library
9 | Properties
10 | EnhancedMonitoring
11 | EnhancedMonitoring
12 | v4.5
13 | 512
14 |
15 |
16 | true
17 | full
18 | false
19 | bin\Debug\
20 | DEBUG;TRACE
21 | prompt
22 | 4
23 |
24 |
25 | pdbonly
26 | true
27 | bin\Release\
28 | TRACE
29 | prompt
30 | 4
31 |
32 |
33 | true
34 | bin\DebugAndRelease\
35 | DEBUG;TRACE
36 | full
37 | AnyCPU
38 | prompt
39 | MinimumRecommendedRules.ruleset
40 |
41 |
42 | true
43 | bin\x64\Debug\
44 | DEBUG;TRACE
45 | full
46 | x64
47 | prompt
48 | MinimumRecommendedRules.ruleset
49 |
50 |
51 | bin\x64\Release\
52 | TRACE
53 | true
54 | pdbonly
55 | x64
56 | prompt
57 | MinimumRecommendedRules.ruleset
58 |
59 |
60 | true
61 | bin\x64\DebugAndRelease\
62 | DEBUG;TRACE
63 | full
64 | x64
65 | prompt
66 | MinimumRecommendedRules.ruleset
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 | Designer
111 |
112 |
113 |
114 |
121 |
--------------------------------------------------------------------------------
/src/Service/EnhacedMonitoringProvider.resx:
--------------------------------------------------------------------------------
1 |
2 |
3 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | text/microsoft-resx
110 |
111 |
112 | 2.0
113 |
114 |
115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
116 |
117 |
118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
119 |
120 |
121 | False
122 |
123 |
--------------------------------------------------------------------------------
/src/EnhancedMonitoring/DataFormat/DataFormatHelper.cs:
--------------------------------------------------------------------------------
1 | //The MIT License (MIT)
2 | //
3 | //Copyright 2015 Microsoft Corporation
4 | //
5 | //Permission is hereby granted, free of charge, to any person obtaining a copy
6 | //of this software and associated documentation files (the "Software"), to deal
7 | //in the Software without restriction, including without limitation the rights
8 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | //copies of the Software, and to permit persons to whom the Software is
10 | //furnished to do so, subject to the following conditions:
11 | //
12 | //The above copyright notice and this permission notice shall be included in
13 | //all copies or substantial portions of the Software.
14 | //
15 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | //THE SOFTWARE.
22 | //
23 | using System;
24 | using System.Collections;
25 | using System.Collections.Generic;
26 | using System.IO;
27 | using System.Linq;
28 | using System.Runtime.Serialization;
29 | using System.Text;
30 | using System.Threading.Tasks;
31 | using System.Web.Script.Serialization;
32 | using System.Xml;
33 | using System.Xml.Linq;
34 |
35 | namespace EnhancedMonitoring.DataFormat
36 | {
37 | public static class DataFormatHelper
38 | {
39 |
40 | public const String ChunkCountKey = "all";
41 | public const String ChunkKey = "data";
42 | public const String TimestampKey = "ts";
43 |
44 | public static String ToJSON(IDictionary data)
45 | {
46 | JavaScriptSerializer jsSerializer = new JavaScriptSerializer();
47 | String jsonStr = jsSerializer.Serialize(data);
48 | return jsonStr;
49 | }
50 |
51 | public static String ToXml(IDictionary data)
52 | {
53 | return DictionaryToXElement("Data", data).ToString();
54 | }
55 |
56 | private static XElement DictionaryToXElement(String nodeName, IDictionary data)
57 | {
58 | nodeName = NormalizeNodeName(nodeName);
59 | XElement node = new XElement(nodeName);
60 | foreach (var entry in data)
61 | {
62 | node.Add(ObjectToXElement(entry.Key, entry.Value));
63 | }
64 | return node;
65 | }
66 |
67 | private static XElement ObjectToXElement(String nodeName, Object nodeContent)
68 | {
69 | nodeName = NormalizeNodeName(nodeName);
70 | if (nodeContent is IList)
71 | {
72 | return ListToXElement(nodeName, nodeContent as IList);
73 | }
74 | else if (nodeContent is IDictionary)
75 | {
76 | return DictionaryToXElement(nodeName, nodeContent as IDictionary);
77 | }
78 | else if(nodeContent == null)
79 | {
80 | return new XElement(nodeName, "null");
81 | }
82 | else
83 | {
84 | return new XElement(nodeName, nodeContent);
85 | }
86 | }
87 |
88 | private static XElement ListToXElement(String nodeName, IList list)
89 | {
90 | nodeName = NormalizeNodeName(nodeName);
91 | XElement node = new XElement(nodeName);
92 | node.SetAttributeValue("Type", "List");
93 | foreach(var elem in list)
94 | {
95 | node.Add(ObjectToXElement("Item", elem));
96 | }
97 | return node;
98 | }
99 | private static string NormalizeNodeName(string nodeName)
100 | {
101 | if (String.IsNullOrEmpty(nodeName))
102 | {
103 | throw new ArgumentException("Node name can't be null or empty.");
104 | }
105 | return nodeName.Trim().Replace(' ', '_');
106 | }
107 |
108 | public static String Base64Encode(String str)
109 | {
110 | var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(str);
111 | String encoded = System.Convert.ToBase64String(plainTextBytes);
112 | return encoded;
113 | }
114 |
115 | public static IList PackString(String str, int blockLength)
116 | {
117 | var packed = new List();
118 | var textBytes = System.Text.Encoding.UTF8.GetBytes(str);
119 |
120 | int i = 0;
121 | while (i < textBytes.Length)
122 | {
123 | packed.Add(System.Text.Encoding.UTF8.GetString(textBytes, i, Math.Min(blockLength, textBytes.Length - i)));
124 | i += blockLength;
125 | }
126 | return packed;
127 | }
128 |
129 | public static IDictionary ToChunk(String keyPrefix, IList dataChunks,
130 | Func, String> baseFormater)
131 | {
132 | var packedData = new Dictionary();
133 |
134 | var timestamp = GetCurrentTime();
135 |
136 | for (int i = 0; i < dataChunks.Count; i++)
137 | {
138 | var dataChunk = new Dictionary();
139 | dataChunk.Add(TimestampKey, timestamp);
140 | dataChunk.Add(ChunkCountKey, dataChunks.Count);
141 | dataChunk.Add(ChunkKey, dataChunks[i]);
142 |
143 | packedData.Add(String.Format("{0}{1}", keyPrefix, i), baseFormater(dataChunk));
144 | }
145 |
146 | return packedData;
147 | }
148 |
149 | public static double GetCurrentTime()
150 | {
151 | //To UNIX like timestamp. Milliseconds since 1970/1/1 00:00:00 UTC
152 | return DateTime.UtcNow
153 | .Subtract(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc))
154 | .TotalMilliseconds;
155 | }
156 | }
157 | }
158 |
--------------------------------------------------------------------------------
/src/UnitTest/TestFileLogWriter.cs:
--------------------------------------------------------------------------------
1 | //The MIT License (MIT)
2 | //
3 | //Copyright 2015 Microsoft Corporation
4 | //
5 | //Permission is hereby granted, free of charge, to any person obtaining a copy
6 | //of this software and associated documentation files (the "Software"), to deal
7 | //in the Software without restriction, including without limitation the rights
8 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | //copies of the Software, and to permit persons to whom the Software is
10 | //furnished to do so, subject to the following conditions:
11 | //
12 | //The above copyright notice and this permission notice shall be included in
13 | //all copies or substantial portions of the Software.
14 | //
15 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | //THE SOFTWARE.
22 | //
23 | using System;
24 | using System.Text;
25 | using System.Collections.Generic;
26 | using Microsoft.VisualStudio.TestTools.UnitTesting;
27 | using EnhancedMonitoring.Configuration;
28 | using EnhancedMonitoring.Logging;
29 | using System.IO;
30 | using System.Threading.Tasks;
31 | using System.Diagnostics;
32 |
33 | namespace UnitTest
34 | {
35 | ///
36 | /// Summary description for TestFileLogWriter
37 | ///
38 | [TestClass]
39 | public class TestFileLogWriter
40 | {
41 |
42 | [TestMethod]
43 | public void TestWriteToLogFile()
44 | {
45 | var tmpFolder = System.Environment.GetFolderPath(System.Environment.SpecialFolder.CommonApplicationData)
46 | + @"\" + Guid.NewGuid().ToString();
47 |
48 | var conf = new MonitorConfiguration()
49 | {
50 | LogLevel = "Info",
51 | LogFilePath = tmpFolder + @"\test.log"
52 | };
53 |
54 | var logWriter = new FileLogWriter(conf);
55 |
56 | String logContent = Guid.NewGuid().ToString();
57 | logWriter.Write(LogLevel.Info, logContent);
58 |
59 | Assert.IsTrue(File.Exists(conf.LogFilePath));
60 | String log = File.ReadAllText(conf.LogFilePath);
61 | Assert.IsTrue(log.Contains(logContent));
62 |
63 | Directory.Delete(tmpFolder, true);
64 | }
65 |
66 | [TestMethod]
67 | public void TestMultithreadWriteToLogFile()
68 | {
69 | var tmpFolder = System.Environment.GetFolderPath(System.Environment.SpecialFolder.CommonApplicationData)
70 | + @"\" + Guid.NewGuid().ToString();
71 |
72 | var conf = new MonitorConfiguration()
73 | {
74 | LogLevel = "Info",
75 | LogFilePath = tmpFolder + @"\test.log"
76 | };
77 |
78 | var logWriter = new FileLogWriter(conf);
79 |
80 | Task[] tasks = new Task[100];
81 | for(int i = 0; i < tasks.Length; i++)
82 | {
83 | tasks[i] = Task.Run(() =>
84 | {
85 | Console.WriteLine(Process.GetCurrentProcess().Threads.Count);
86 | String logContent = Guid.NewGuid().ToString();
87 | logWriter.Write(LogLevel.Info, logContent);
88 |
89 | });
90 | }
91 | Task.WaitAll(tasks);
92 | Directory.Delete(tmpFolder, true);
93 | }
94 |
95 | [TestMethod]
96 | public void TestRotateLog()
97 | {
98 | var tmpFolder = System.Environment.GetFolderPath(System.Environment.SpecialFolder.CommonApplicationData)
99 | + @"\" + Guid.NewGuid().ToString();
100 |
101 | Console.WriteLine(tmpFolder);
102 | Directory.CreateDirectory(tmpFolder);
103 | var conf = new MonitorConfiguration()
104 | {
105 | LogLevel = "Info",
106 | LogFilePath = tmpFolder + @"\test.log",
107 | LogFileSize = 1,
108 | MaxLogRetention = 2
109 | };
110 |
111 | var logWriter = new FileLogWriter(conf);
112 |
113 | String[] logContent = new String[4]
114 | {
115 | "Test 0","Test 1","Test 2","Test 3",
116 | };
117 |
118 | //echo "Test 0" > test.log
119 | logWriter.Write(LogLevel.Info, logContent[0]);
120 | //mv test.log test.log.0
121 | //echo "Test 1" > test.log
122 | logWriter.Write(LogLevel.Info, logContent[1]);
123 |
124 | Assert.IsTrue(File.Exists(conf.LogFilePath));
125 | String log = File.ReadAllText(conf.LogFilePath);
126 | Assert.IsTrue(log.Contains(logContent[1]));
127 |
128 | Assert.IsTrue(File.Exists(conf.LogFilePath + @".0"));
129 | log = File.ReadAllText(conf.LogFilePath + @".0");
130 | Assert.IsTrue(log.Contains(logContent[0]));
131 |
132 | //mv test.log.0 test.log.1
133 | //mv test.log test.log.0
134 | //echo "Test 2" > test.log
135 | logWriter.Write(LogLevel.Info, logContent[2]);
136 |
137 | //rm test.log.1
138 | //mv test.log.0 test.log.1
139 | //mv test.log test.log.0
140 | //echo "Test 3" test.log
141 | logWriter.Write(LogLevel.Info, logContent[3]);
142 |
143 | Assert.IsTrue(File.Exists(conf.LogFilePath + @".0"));
144 | Assert.IsTrue(File.Exists(conf.LogFilePath + @".1"));
145 | Assert.IsFalse(File.Exists(conf.LogFilePath + @".2"));
146 |
147 | log = File.ReadAllText(conf.LogFilePath);
148 | Assert.IsTrue(log.Contains(logContent[3]));
149 |
150 |
151 | log = File.ReadAllText(conf.LogFilePath + @".1");
152 | Assert.IsTrue(log.Contains(logContent[1]));
153 |
154 | Directory.Delete(tmpFolder, true);
155 | }
156 |
157 | }
158 | }
159 |
--------------------------------------------------------------------------------
/src/UnitTest/UnitTest.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug
5 | AnyCPU
6 | {0B568E5B-3796-47CC-B934-C4684CBE241C}
7 | Library
8 | Properties
9 | UnitTest
10 | UnitTest
11 | v4.5
12 | 512
13 | {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}
14 | 10.0
15 | $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)
16 | $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages
17 | False
18 | UnitTest
19 |
20 |
21 | true
22 | full
23 | false
24 | bin\Debug\
25 | DEBUG;TRACE
26 | prompt
27 | 4
28 | x64
29 |
30 |
31 | pdbonly
32 | true
33 | bin\Release\
34 | TRACE
35 | prompt
36 | 4
37 |
38 |
39 | true
40 | bin\DebugAndRelease\
41 | DEBUG;TRACE
42 | full
43 | AnyCPU
44 | prompt
45 | MinimumRecommendedRules.ruleset
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 | Designer
89 |
90 |
91 |
92 |
93 |
94 | {7eacc378-2947-4f2e-ab0f-eb57be7d3680}
95 | EnhancedMonitoring
96 |
97 |
98 |
99 |
100 |
101 |
102 | False
103 |
104 |
105 | False
106 |
107 |
108 | False
109 |
110 |
111 | False
112 |
113 |
114 |
115 |
116 |
117 |
118 |
125 |
--------------------------------------------------------------------------------
/src/EnhancedMonitoring/KeyValuePairWriter.cs:
--------------------------------------------------------------------------------
1 | //The MIT License (MIT)
2 | //
3 | //Copyright 2015 Microsoft Corporation
4 | //
5 | //Permission is hereby granted, free of charge, to any person obtaining a copy
6 | //of this software and associated documentation files (the "Software"), to deal
7 | //in the Software without restriction, including without limitation the rights
8 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | //copies of the Software, and to permit persons to whom the Software is
10 | //furnished to do so, subject to the following conditions:
11 | //
12 | //The above copyright notice and this permission notice shall be included in
13 | //all copies or substantial portions of the Software.
14 | //
15 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | //THE SOFTWARE.
22 | //
23 | using EnhancedMonitoring.Configuration;
24 | using System;
25 | using System.Collections.Generic;
26 | using System.Linq;
27 | using System.Management;
28 | using System.Text;
29 | using System.Threading.Tasks;
30 |
31 | namespace EnhancedMonitoring
32 | {
33 | public class KeyValuePairWriter : IDisposable
34 | {
35 | protected const String WMI_Namespace = @"root\virtualization\v2";
36 | protected const String WMI_Class_Msvm_ComputerSystem = @"Msvm_ComputerSystem";
37 | protected const String WMI_Class_Msvm_VirtualSystemManagementService = @"Msvm_VirtualSystemManagementService";
38 | protected const String WMI_Class_Msvm_KvpExchangeDataItem = @"Msvm_KvpExchangeDataItem";
39 | protected const Int32 DEFAULT_WRITE_INTERVAL = 100;
40 |
41 | public static KeyValuePairWriter CreateInstance(KvpConfiguration conf)
42 | {
43 | return new KeyValuePairWriter(conf);
44 | }
45 |
46 | private bool batchMode = false;
47 | private Int32 writeInterval = DEFAULT_WRITE_INTERVAL;
48 |
49 | protected KeyValuePairWriter(KvpConfiguration conf)
50 | {
51 | if(conf != null)
52 | {
53 | this.batchMode = conf.BatchMode;
54 | this.writeInterval = conf.WriteInterval <= 0 ? DEFAULT_WRITE_INTERVAL : conf.WriteInterval;
55 | }
56 | }
57 |
58 | public void Remove(IDictionary args, IDictionary data)
59 | {
60 | InvokeKvpOperation(args, data, "RemoveKvpItems");
61 | }
62 |
63 | public void Write(IDictionary args, IDictionary data)
64 | {
65 | InvokeKvpOperation(args, data, "AddKvpItems");
66 | }
67 |
68 | protected void InvokeKvpOperation(IDictionary args, IDictionary data, String operationName)
69 | {
70 | if (args == null)
71 | {
72 | throw new ArgumentNullException("args");
73 | }
74 |
75 | if (data == null)
76 | {
77 | throw new ArgumentNullException("data");
78 | }
79 |
80 | if (data.Count() == 0)
81 | {
82 | return;
83 | }
84 |
85 | var kvpItems = ToKvpItems(data);
86 | using (var vmMgmt = WMIHelper.GetFirstInstance(WMI_Namespace, WMI_Class_Msvm_VirtualSystemManagementService))
87 | using (var vm = WMIHelper.QueryFirstInstacne(WMI_Namespace, WMI_Class_Msvm_ComputerSystem, String.Format("Name='{0}'", args["VirtualMachineName"])))
88 | {
89 | if(batchMode)
90 | {
91 | InvokeKvpOperation(vmMgmt, vm, operationName, kvpItems);
92 | }
93 | else
94 | {
95 | foreach (var kvpItem in kvpItems)
96 | {
97 | InvokeKvpOperation(vmMgmt, vm, operationName, new String[] { kvpItem });
98 | }
99 | }
100 |
101 | }
102 | }
103 |
104 | protected void InvokeKvpOperation(ManagementObject vmMgmt, ManagementObject vm, String operationName, String[] kvpItems)
105 | {
106 | using (var inParams = vmMgmt.GetMethodParameters(operationName))
107 | {
108 | inParams["DataItems"] = kvpItems;
109 | inParams["TargetSystem"] = vm;
110 |
111 | using (var outParams = vmMgmt.InvokeMethod(operationName, inParams, null))
112 | {
113 | //Delay a small mount of time to avoid overwhelm the KVP VSC in the guest.
114 | Task.Delay(this.writeInterval);
115 | WMIHelper.WaitForAsyncJob(outParams, WMI_Namespace);
116 | }
117 | }
118 | }
119 |
120 | protected static String ToKvpItem(KeyValuePair kvp)
121 | {
122 | using (var kvpItem = WMIHelper.CreateInstance(WMI_Namespace, WMI_Class_Msvm_KvpExchangeDataItem))
123 | {
124 | kvpItem["Name"] = kvp.Key;
125 | kvpItem["Data"] = kvp.Value;
126 | kvpItem["Source"] = 0;
127 | return ((ManagementBaseObject)kvpItem).GetText(TextFormat.CimDtd20);
128 | }
129 | }
130 |
131 | protected static String[] ToKvpItems(IDictionary data)
132 | {
133 | var dataItems = data.Select((kvp) =>
134 | {
135 | return ToKvpItem(kvp);
136 | }).ToArray();
137 | return dataItems;
138 | }
139 |
140 | #region IDisposable
141 | bool disposed = false;
142 |
143 | public void Dispose()
144 | {
145 | // Dispose of unmanaged resources.
146 | Dispose(true);
147 | // Suppress finalization.
148 | GC.SuppressFinalize(this);
149 | }
150 | // Protected implementation of Dispose pattern.
151 | protected virtual void Dispose(bool disposing)
152 | {
153 | if (disposed)
154 | return;
155 |
156 | if (disposing)
157 | {
158 |
159 | }
160 |
161 | disposed = true;
162 | }
163 | #endregion
164 |
165 | }
166 | }
167 |
--------------------------------------------------------------------------------
/src/EnhancedMonitoring/DataCollector/QueryMgmtObject.cs:
--------------------------------------------------------------------------------
1 | //The MIT License (MIT)
2 | //
3 | //Copyright 2015 Microsoft Corporation
4 | //
5 | //Permission is hereby granted, free of charge, to any person obtaining a copy
6 | //of this software and associated documentation files (the "Software"), to deal
7 | //in the Software without restriction, including without limitation the rights
8 | //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | //copies of the Software, and to permit persons to whom the Software is
10 | //furnished to do so, subject to the following conditions:
11 | //
12 | //The above copyright notice and this permission notice shall be included in
13 | //all copies or substantial portions of the Software.
14 | //
15 | //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 | //THE SOFTWARE.
22 | //
23 | using EnhancedMonitoring.Configuration;
24 | using EnhancedMonitoring.Logging;
25 | using System;
26 | using System.Collections.Generic;
27 | using System.Linq;
28 | using System.Management;
29 | using System.Text;
30 | using System.Threading.Tasks;
31 |
32 | namespace EnhancedMonitoring.DataCollector
33 | {
34 | public class QueryMgmtObject : MgmtObject
35 | {
36 |
37 | private String[] selectedProperties;
38 |
39 | internal QueryMgmtObject(MgmtObjectConfiguration conf) : base(conf)
40 | {
41 | //If specific perf count is given, instead of "*", which means select all,
42 | // we should construct an array of selected properties and parse it through WQL query to improve performance
43 | if (this.conf.PerfCounters != null && this.conf.PerfCounters.Count != 0
44 | && !this.conf.PerfCounters.Any(counter => !String.IsNullOrEmpty(counter.Select) && counter.Select.Equals("*")))
45 | {
46 | //The properties start with "_" needs to be handled specially.
47 | //Like "_Path", it is not in Properties set, which is by the design of .net's WMI libary.
48 | this.selectedProperties = this.conf.PerfCounters
49 | .Select(counter => counter.Select).Where(p => !String.IsNullOrEmpty(p) && !p.StartsWith("_")).ToArray();
50 | }
51 | }
52 |
53 | ///
54 | ///
55 | ///
56 | /// Named arguments used in "Where" field of WQL query
57 | ///
58 | public override Object CollectData(IDictionary args)
59 | {
60 | if(args == null)
61 | {
62 | throw new ArgumentNullException("args");
63 | }
64 |
65 | if (this.conf.PerfCounters == null)
66 | {
67 | return null;
68 | }
69 |
70 | String condition = String.Empty;
71 |
72 | condition = NamedArgumentHelper.Resolve(this.conf.Where, this.conf.WhereArgs, args);
73 |
74 | if (this.conf.PerfCounters == null || this.conf.PerfCounters.Count == 0)
75 | {
76 | return null;
77 | }
78 |
79 | using (var result = WMIHelper.QueryInstacnes(this.conf.Namespace, this.conf.From, condition, this.selectedProperties))
80 | {
81 | var mgmtObjs = result.Cast();
82 | if(this.conf.ReturnValueType == MgmtObjectReturnValueType.Single)
83 | {
84 | var mgmtObj = mgmtObjs.FirstOrDefault();
85 | return SelectPerfCounter(mgmtObj, args);
86 | }
87 | else
88 | {
89 | var list = new List