| 
						
						
							
								
							
						
						
					 | 
				
				 | 
				
					@ -25,7 +25,8 @@ import ( | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						"io/ioutil" | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						"sort" | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						"bytes" | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						"errors" | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						"github.com/namsral/flag" | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						"github.com/prometheus/client_golang/prometheus" | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						"github.com/prometheus/client_golang/prometheus/promhttp" | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				
					@ -37,6 +38,7 @@ const serviceLoadRetryTime = 1 * time.Minute | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					var ( | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						flag_test = flag.Bool("test", false, "print all available metrics to stdout") | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						flag_collect = flag.Bool("collect", false, "print configured metrics to stdout and exit") | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						flag_jsonout = flag.String("json-out", "", "store metrics also to JSON file when running test") | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						  | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						flag_addr = flag.String("listen-address", "127.0.0.1:9042", "The address to listen on for HTTP requests.") | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				
					@ -61,10 +63,18 @@ type JSON_PromDesc struct { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						VarLabels	[]string	`json:"varLabels"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					type ActionArg struct { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						Name string				`json:"Name"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						IsIndex bool			`json:"IsIndex"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						ProviderAction string	`json:"ProviderAction"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						Value string			`json:"Value"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					type Metric struct { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						// initialized loading JSON
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						Service	string		`json:"service"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						Action	string		`json:"action"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						ActionArgument	*ActionArg	`json:"actionArgument"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						Result	string		`json:"result"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						OkValue	string		`json:"okValue"` | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						PromDesc	JSON_PromDesc		`json:"promDesc"` | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				
					@ -87,6 +97,29 @@ type FritzboxCollector struct { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						Root       *upnp.Root | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					// simple ResponseWriter to collect output
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					type TestResponseWriter struct { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						header		http.Header | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						statusCode	int | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						body		bytes.Buffer | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					func (w *TestResponseWriter) Header() http.Header { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						return w.header | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					func (w *TestResponseWriter) Write(b []byte) (int, error) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						return w.body.Write(b) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					func (w *TestResponseWriter) WriteHeader(statusCode int) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						w.statusCode = statusCode | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					func (w *TestResponseWriter) String() string { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						return w.body.String() | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					// LoadServices tries to load the service information. Retries until success.
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					func (fc *FritzboxCollector) LoadServices() { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						for { | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
				 | 
				
					@ -113,6 +146,72 @@ func (fc *FritzboxCollector) Describe(ch chan<- *prometheus.Desc) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					func (fc *FritzboxCollector) ReportMetric(ch chan<- prometheus.Metric, m *Metric, val interface{}) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						var floatval float64 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						switch tval := val.(type) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							case uint64: | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								floatval = float64(tval) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							case bool: | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								if tval { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
									floatval = 1 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								} else { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
									floatval = 0 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							case string: | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								if tval == m.OkValue { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
									floatval = 1 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								} else { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
									floatval = 0 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							default: | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								fmt.Println("unknown type", val) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								collect_errors.Inc() | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								return | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						ch <- prometheus.MustNewConstMetric( | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							m.Desc, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							m.MetricType, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							floatval, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							fc.Gateway, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						)	 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					func (fc *FritzboxCollector) GetActionResult(result_map map[string]upnp.Result, serviceType string, actionName string, actionArg *upnp.ActionArgument) (upnp.Result, error) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						m_key := serviceType+"|"+actionName | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						// for calls with argument also add arguement name and value to key	
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						if actionArg != nil { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							m_key += "|"+actionArg.Name+"|"+fmt.Sprintf("%v", actionArg.Value) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						last_result	:= result_map[m_key]; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						if last_result == nil { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							service, ok := fc.Root.Services[serviceType] | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							if !ok { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								return nil, errors.New(fmt.Sprintf("service %s not found", serviceType))	 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							action, ok := service.Actions[actionName] | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							if !ok { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								return nil, errors.New(fmt.Sprintf("action %s not found in service %s", actionName, serviceType))	 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							var err error | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							last_result, err = action.Call(actionArg); | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							if err != nil { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								return nil, err | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							result_map[m_key]=last_result | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						return last_result, nil | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					func (fc *FritzboxCollector) Collect(ch chan<- prometheus.Metric) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						fc.Lock() | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						root := fc.Root | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				
					@ -123,73 +222,57 @@ func (fc *FritzboxCollector) Collect(ch chan<- prometheus.Metric) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							return | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						var err error | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						// create a map for caching results
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						var result_map = make(map[string]upnp.Result) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						for _, m := range metrics { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							m_key := m.Service+"|"+m.Action | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							last_result	:= result_map[m_key]; | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							if last_result == nil { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								service, ok := root.Services[m.Service] | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								if !ok { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
									// TODO
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
									fmt.Println("cannot find service", m.Service) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
									fmt.Println(root.Services) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
									continue | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								action, ok := service.Actions[m.Action] | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								if !ok { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
									// TODO
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
									fmt.Println("cannot find action", m.Action) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
									continue | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							var actArg *upnp.ActionArgument | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							if m.ActionArgument != nil { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								aa := m.ActionArgument | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								var value interface {}   | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								value = aa.Value | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								  | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								if aa.ProviderAction != "" { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
									provRes, err := fc.GetActionResult(result_map, m.Service, aa.ProviderAction, nil) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
									if err != nil { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
										fmt.Printf("Error getting provider action %s result for %s.%s: %s\n", aa.ProviderAction, m.Service, m.Action, err.Error()) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
										collect_errors.Inc() | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
										continue | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
									} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
									 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
									var ok bool | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
									value, ok = provRes[aa.Value]		// Value contains the result name for provider actions
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
									if !ok { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
										fmt.Printf("provider action %s for %s.%s has no result %s", m.Service, m.Action, aa.Value) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
										collect_errors.Inc() | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
										continue | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
									} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								last_result, err = action.Call() | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								if err != nil { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
									fmt.Println(err) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
									collect_errors.Inc() | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
									continue | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								if aa.IsIndex { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
									// TODO handle index iterations
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								} else { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
									actArg = &upnp.ActionArgument{Name: aa.Name, Value: value } | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								result_map[m_key]=last_result | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							}  | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							result, err := fc.GetActionResult(result_map, m.Service, m.Action, actArg) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							val, ok := last_result[m.Result] | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							if !ok { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								fmt.Println("result not found", m.Result) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							if err != nil { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								fmt.Println(err.Error()) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								collect_errors.Inc() | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								continue | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								continue			 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							var floatval float64 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							switch tval := val.(type) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							case uint64: | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								floatval = float64(tval) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							case bool: | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								if tval { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
									floatval = 1 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								} else { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
									floatval = 0 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							case string: | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								if tval == m.OkValue { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
									floatval = 1 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								} else { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
									floatval = 0 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							default: | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								fmt.Println("unknown", val) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							val, ok := result[m.Result] | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							if !ok { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								fmt.Printf("%s.%s has no result %s", m.Service, m.Action, m.Result) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								collect_errors.Inc() | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								continue | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							ch <- prometheus.MustNewConstMetric( | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								m.Desc, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								m.MetricType, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								floatval, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								fc.Gateway, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							fc.ReportMetric(ch, m, val) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
				 | 
				
					@ -219,26 +302,20 @@ func test() { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							sort.Strings(actionKeys) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							for _, l := range actionKeys { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								a := s.Actions[l] | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								if !a.IsGetOnly() { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
									fmt.Printf("  %s - not calling - arguments: variable [direction] (soap name, soap type\n", a.Name) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
									for _, arg := range a.Arguments { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
										sv := arg.StateVariable | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
										fmt.Printf("    %s [%s] (%s, %s)\n", arg.RelatedStateVariable, arg.Direction, arg.Name, sv.DataType) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					       				} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
									continue | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								fmt.Printf("  %s - arguments: variable [direction] (soap name, soap type)\n", a.Name) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								for _, arg := range a.Arguments { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
									sv := arg.StateVariable | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
									fmt.Printf("    %s [%s] (%s, %s)\n", arg.RelatedStateVariable, arg.Direction, arg.Name, sv.DataType) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								fmt.Printf("  %s\n", a.Name) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								res, err := a.Call() | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								if err != nil { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
									fmt.Printf("    FAILED:%s\n", err.Error()) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								if !a.IsGetOnly() { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
									fmt.Printf("  %s - not calling, since arguments required or no output\n", a.Name) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
									continue | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								// only create JSON for Get
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								// TODO also create JSON templates for input actionParams 
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								for _, arg := range a.Arguments { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
									fmt.Printf("    %s: %v\n", arg.RelatedStateVariable, res[arg.StateVariable.Name]) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
									// create new json entry				
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
									if(newEntry) { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
										json.WriteString(",\n") | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				
					@ -254,6 +331,18 @@ func test() { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
									json.WriteString(arg.RelatedStateVariable) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
									json.WriteString("\"\n\t}") | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								fmt.Printf("  %s - calling - results: variable: value\n", a.Name) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								res, err := a.Call(nil) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								if err != nil { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
									fmt.Printf("    FAILED:%s\n", err.Error()) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
									continue | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								for _, arg := range a.Arguments { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
									fmt.Printf("    %s: %v\n", arg.RelatedStateVariable, res[arg.StateVariable.Name]) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
								} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						 | 
				
			
			
		
	
	
		
			
				
					| 
						
							
								
							
						
						
							
								
							
						
						
					 | 
				
				 | 
				
					@ -320,7 +409,25 @@ func main() { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							Username: *flag_gateway_username, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							Password: *flag_gateway_password, | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						if *flag_collect { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							collector.LoadServices() | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							prometheus.MustRegister(collector) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							prometheus.MustRegister(collect_errors) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							fmt.Println("collecting metrics via http") | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							// simulate HTTP request without starting actual http server
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							writer := TestResponseWriter{header: http.Header{}} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							request := http.Request{} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							promhttp.Handler().ServeHTTP(&writer, &request)  | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							fmt.Println(writer.String()) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							return | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						} | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
							 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						go collector.LoadServices() | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						prometheus.MustRegister(collector) | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
							
								
							
						
					 | 
				
				 | 
				
					@ -328,5 +435,6 @@ func main() { | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						http.Handle("/metrics", promhttp.Handler()) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						fmt.Printf("metrics available at http://%s/metrics\n", *flag_addr) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					
 | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
						log.Fatal(http.ListenAndServe(*flag_addr, nil)) | 
				
			
			
		
	
		
			
				
					 | 
					 | 
				
				 | 
				
					} | 
				
			
			
		
	
	
		
			
				
					| 
						
						
						
					 | 
				
				 | 
				
					
  |