bosun.org@v0.0.0-20210513094433-e25bc3e69a1f/util/Windows_WMI_Metadata.linq (about)

     1  <Query Kind="Program">
     2    <Reference>&lt;RuntimeDirectory&gt;\System.Management.dll</Reference>
     3    <Reference>&lt;RuntimeDirectory&gt;\System.Configuration.Install.dll</Reference>
     4    <Reference>&lt;RuntimeDirectory&gt;\Microsoft.JScript.dll</Reference>
     5    <Namespace>System.Management</Namespace>
     6  </Query>
     7  
     8  //LinqPad script used to codegen metadata for WMI classes
     9  void Main()
    10  {
    11  	//Follow steps 1-4 to generate the GO code from a wmi class
    12  	//See step 1 at bottom of page.
    13  	string strPrefix = "descWinSystem"; 	//Step 2: Set this to the prefix you want to use for metadata
    14  	string server = "localhost";  		//Step 3: Change this to another server if you need specific WMI information
    15  	string WMIClass = "Win32_PerfRawData_PerfOS_System"; //Step 4: WMI class for which you want to find metadata
    16  	bool GenerateFromMSDNClass = true; //Set to true if using an MSDN class in step 1. Set to false if text is an existing Add/AddTS block of code.
    17  	
    18  	//Load details about WMI Class and properties
    19  	var htWMIDetails = new Dictionary<string,WMIDetail>(StringComparer.InvariantCultureIgnoreCase);
    20  	ManagementScope s = new ManagementScope(string.Format("\\\\{0}\\root\\cimv2", server));
    21      ManagementPath p = new ManagementPath(WMIClass);
    22      ObjectGetOptions o = new ObjectGetOptions(null, System.TimeSpan.MaxValue, true);
    23      ManagementClass osClass = new ManagementClass(s, p, o);
    24  	osClass.Options.UseAmendedQualifiers = true; //Adds Description details (which are missing otherwise)
    25  	//osClass.Properties.Dump();
    26  	foreach (PropertyData property in osClass.Properties)
    27  	{
    28  		WMIDetail d = WMIDetail.FromPropertyData(property);
    29  		//d.Dump();
    30  		htWMIDetails.Add(property.Name, d);
    31  	}
    32  	//htWMIDetails.Values.Dump("WMI Details");
    33  	if(string.IsNullOrWhiteSpace(text)){
    34  		StringBuilder sbText = new StringBuilder();
    35  		foreach(var key in htWMIDetails.Keys){
    36  			sbText.AppendFormat("{0};\r\n",key);
    37  		}
    38  		text = sbText.ToString();
    39  	}
    40  	
    41  	//text.Dump("Input lines pre transform");
    42  	var PropertiesUsed = new List<string>();
    43  	var matches = new List<Match>();
    44  	int countLines = -1;
    45  	using (StringReader sr = new StringReader(text)) {
    46  		string line;
    47  		while ((line = sr.ReadLine()) != null) {
    48  			countLines++;
    49  			if(GenerateFromMSDNClass){
    50  				//Regex to parse metrics out of the class ___ : ____ found on MSDN pages
    51  				var m = Regex.Match(line, @"(?<wmiName>[^ ;\{\}]+);$", RegexOptions.Multiline);
    52  				if(m.Success){
    53  					matches.Add(m);
    54  					PropertiesUsed.Add(m.Groups["wmiName"].Value);
    55  				}
    56  			} else {
    57  				//Regex to parse out the details from an Add or AddTS line in a *_windows.go. Change ""(?<metric>[^"",]*)"" to ""?(?<metric>[^"",]*)""? to capture osXXX based metrics
    58  				var m = Regex.Match(line, @"\s{0,4}Add\(&md, ""(?<metric>[^"",]*)"", v\.(?<wmiName>[a-zA-Z_]*)[^,]*, (nil|opentsdb.TagSet\{(?<tagset>[^}]*)\}), metadata\.(?<type>[^\,]*), metadata\.(?<units>[^\,]*), (""""|[a-zA-Z_]*)\)", RegexOptions.Multiline); //Get wmi details
    59  				if(m.Success){
    60  					matches.Add(m);
    61  					//m.Groups.Dump();
    62  					//m.Groups["tagset"].Value.Dump();
    63  					var t = Regex.Match(m.Groups["tagset"].Value, @"'site': v.Name, '(?<tagkey>[^']*)': '(?<tagvalue>[^']*)'", RegexOptions.Singleline); //Get tag names
    64  					//t.Dump();
    65  					if(t.Success){ //Use different identifier for lines with tags?
    66  						//result.Add(string.Format("{0}_{1}", m.Groups["wmiName"].Value,t.Groups["tagvalue"].Value));
    67  						PropertiesUsed.Add(m.Groups["wmiName"].Value);
    68  					} else {
    69  						PropertiesUsed.Add(m.Groups["wmiName"].Value);
    70  					}				
    71  				}
    72  			}
    73  		}//while
    74  	}//using
    75  	countLines.Dump("Total Lines pre-processing:");
    76  	PropertiesUsed.Distinct().Count().Dump("Distinct WMI Properties detected:");
    77  	//PropertiesUsed.Dump("WMI Properties used in the text block");	
    78  	
    79  	
    80  	if(GenerateFromMSDNClass){
    81  	    //Create lines for adding metric and for the GO struct
    82  		Console.WriteLine("//Metrics:");
    83  		foreach(var m in matches){
    84  			WMIDetail details;
    85  			if(htWMIDetails.TryGetValue(m.Groups["wmiName"].Value, out details)) {
    86  				Console.WriteLine("Add(&md, \"win.system.{0}\", v.{0}, tags, metadata.Counter, metadata.PerSecond, {1}{0})", details.Name,strPrefix);
    87  			}
    88  		}
    89  	}
    90  	
    91  	//Generate const for metadata
    92  	var sb = new StringBuilder("Errors:\r\n");
    93  	Console.WriteLine("\r\nconst (");
    94  	foreach(var wmiproperty in PropertiesUsed){
    95  		WMIDetail details;
    96  		if(htWMIDetails.TryGetValue(wmiproperty, out details)) {
    97  			Console.WriteLine(string.Format("  {2}{0} = \"{1}\"", details.Name,details.Description,strPrefix));
    98  		} else {
    99  		 	sb.AppendLine(string.Format("Could not find WMIDetail for '{0}'. Make sure it matches the WMI Property below. (Case Sensitive)", wmiproperty));
   100  		}
   101  	}
   102  	Console.WriteLine(")\r\n");
   103  	if(sb.Length > 9){
   104  		Console.WriteLine(sb.ToString());
   105  	} 
   106  	
   107  	if(GenerateFromMSDNClass){
   108  		Console.WriteLine("\r\ntype {0} struct {{", WMIClass);
   109  		foreach(var m in matches){
   110  			WMIDetail details;
   111  			if(htWMIDetails.TryGetValue(m.Groups["wmiName"].Value, out details)) {
   112  				Console.WriteLine("  {0} {1}", details.Name, details.CIMTYPE);
   113  			}
   114  		}
   115  		Console.WriteLine("}\r\n");
   116  	} else {
   117  		Console.WriteLine("\r\n//Insert metadata variable to Add/AddTS method call");
   118  		foreach(var m in matches){
   119  			var desc = string.Format("{1}{0}", m.Groups["wmiName"].Value,strPrefix);
   120  			var line = m.Value.Replace("\"\")",""+desc+")");
   121  			line = line.Replace("metadata.Unknown", "metadata.Counter"); //Default to counter, must manually set gauge types.
   122  			Console.WriteLine(line);
   123  		}
   124  	}
   125  	
   126  	Console.WriteLine("\r\n//WMI Counter Types");
   127  	foreach(var m in matches){
   128  		WMIDetail details;
   129  		if(htWMIDetails.TryGetValue(m.Groups["wmiName"].Value, out details)) {
   130  			Console.WriteLine("{0} {1}", details.CounterType, details.Name);
   131  		} else {
   132  			Console.WriteLine("No WMIDetails for {0}", m.Groups["wmiName"].Value);
   133  		}
   134  	} 
   135  	
   136  	htWMIDetails.Values.Dump("WMI Property Details");
   137  }
   138  class WMIDetail {
   139  	public WMIDetail()
   140  	{
   141  	}
   142  	public WMIDetail(string name, string cimtype, string countertype, string description, string displayname)
   143  	{
   144  		this.Name = name;
   145  		this.CIMTYPE = cimtype;
   146  		this.CounterType = countertype;
   147  		this.Description = description;
   148  		this.DisplayName = displayname;
   149  	}
   150  	
   151  	public static WMIDetail FromPropertyData(PropertyData property){
   152  		var result = new WMIDetail();
   153  		result.Name = property.Name;
   154  		foreach(System.Management.QualifierData item in property.Qualifiers){
   155  			switch (item.Name)
   156  			{
   157  				case "CIMTYPE":
   158  					result.CIMTYPE = item.Value.ToString();
   159  					break;
   160  				case "CounterType":
   161  					result.CounterType = item.Value.ToString();
   162  					break;
   163  				case "Description":
   164  					result.Description = item.Value.ToString();
   165  					break;
   166  				case "DisplayName":
   167  					result.DisplayName = item.Value.ToString();
   168  					break;
   169  			}
   170  		}
   171  		return result;
   172  	}
   173  	
   174  	public string Name { get; set; }
   175  	public string CIMTYPE { get; set; }
   176  	public string CounterType { get; set; }
   177  	public string Description { get; set; }
   178  	public string DisplayName { get; set; }
   179  }
   180  
   181  //Step 1: Paste MSDN class here. Remove any lines you don't want in your go struct.
   182  //Step 1: Paste current block of GO "Add()" lines here. Then replace " with "" to fix escapping.
   183  string text = @"
   184    uint32 ExceptionDispatchesPerSec;
   185    uint64 FileControlBytesPerSec;
   186    uint32 FileControlOperationsPerSec;
   187    uint32 FileDataOperationsPerSec;
   188    uint64 FileReadBytesPerSec;
   189    uint32 FileReadOperationsPerSec;
   190  ";
   191  //Step 1: Or use empty string for all properties
   192  //string text = "";