refactor and removing unused code

This commit is contained in:
Alexander Zobnin
2020-06-02 17:18:38 +03:00
parent a5f8eb02bb
commit ff0b8b9dff
4 changed files with 50 additions and 194 deletions

View File

@@ -2,32 +2,19 @@ package main
import ( import (
"context" "context"
"crypto/tls"
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
"net"
"net/http"
"net/url"
"time" "time"
"github.com/alexanderzobnin/grafana-zabbix/pkg/gtime" "github.com/alexanderzobnin/grafana-zabbix/pkg/gtime"
"github.com/alexanderzobnin/grafana-zabbix/pkg/zabbixapi" "github.com/alexanderzobnin/grafana-zabbix/pkg/zabbixapi"
hclog "github.com/hashicorp/go-hclog"
plugin "github.com/hashicorp/go-plugin"
"github.com/grafana/grafana-plugin-sdk-go/backend" "github.com/grafana/grafana-plugin-sdk-go/backend"
"github.com/grafana/grafana-plugin-sdk-go/backend/log" "github.com/grafana/grafana-plugin-sdk-go/backend/log"
"github.com/grafana/grafana-plugin-sdk-go/data" "github.com/grafana/grafana-plugin-sdk-go/data"
) )
// ZabbixPlugin implements the Grafana backend interface and forwards queries to the ZabbixDatasourceInstance
type ZabbixPlugin struct {
plugin.NetRPCUnsupportedPlugin
logger hclog.Logger
datasourceCache *Cache
}
type ZabbixDatasource struct { type ZabbixDatasource struct {
datasourceCache *Cache datasourceCache *Cache
logger log.Logger logger log.Logger
@@ -36,25 +23,32 @@ type ZabbixDatasource struct {
// ZabbixDatasourceInstance stores state about a specific datasource // ZabbixDatasourceInstance stores state about a specific datasource
// and provides methods to make requests to the Zabbix API // and provides methods to make requests to the Zabbix API
type ZabbixDatasourceInstance struct { type ZabbixDatasourceInstance struct {
url *url.URL
authToken string
zabbixAPI *zabbixapi.ZabbixAPI zabbixAPI *zabbixapi.ZabbixAPI
dsInfo *backend.DataSourceInstanceSettings dsInfo *backend.DataSourceInstanceSettings
Settings *ZabbixDatasourceSettings Settings *ZabbixDatasourceSettings
queryCache *Cache queryCache *Cache
httpClient *http.Client
logger log.Logger logger log.Logger
} }
// NewZabbixDatasource returns new datasource instance. // NewZabbixDatasourceInstance returns an initialized zabbix datasource instance
func (ds *ZabbixDatasource) NewZabbixDatasource(dsInfo *backend.DataSourceInstanceSettings) (*ZabbixDatasourceInstance, error) { func NewZabbixDatasourceInstance(dsInfo *backend.DataSourceInstanceSettings) (*ZabbixDatasourceInstance, error) {
dsInstance, err := newZabbixDatasource(dsInfo) zabbixAPI, err := zabbixapi.New(dsInfo.URL)
if err != nil { if err != nil {
return nil, err return nil, err
} }
dsInstance.logger = ds.logger zabbixSettings, err := readZabbixSettings(dsInfo)
return dsInstance, nil if err != nil {
return nil, err
}
return &ZabbixDatasourceInstance{
dsInfo: dsInfo,
zabbixAPI: zabbixAPI,
Settings: zabbixSettings,
queryCache: NewCache(zabbixSettings.CacheTTL, 10*time.Minute),
logger: log.New(),
}, nil
} }
// CheckHealth checks if the plugin is running properly // CheckHealth checks if the plugin is running properly
@@ -114,59 +108,36 @@ func (ds *ZabbixDatasource) QueryData(ctx context.Context, req *backend.QueryDat
return qdr, nil return qdr, nil
} }
// func (p *ZabbixPlugin) GetDatasourceById(datasourceId int64) (*ZabbixDatasourceInstance, error) { // GetDatasource Returns cached datasource or creates new one
// } func (ds *ZabbixDatasource) GetDatasource(pluginContext backend.PluginContext) (*ZabbixDatasourceInstance, error) {
dsSettings := pluginContext.DataSourceInstanceSettings
dsKey := fmt.Sprintf("%d-%d", pluginContext.OrgID, dsSettings.ID)
// Get hash to check if settings changed
dsInfoHash := HashDatasourceInfo(dsSettings)
// newZabbixDatasource returns an initialized ZabbixDatasource if cachedData, ok := ds.datasourceCache.Get(dsKey); ok {
func newZabbixDatasource(dsInfo *backend.DataSourceInstanceSettings) (*ZabbixDatasourceInstance, error) { if cachedDS, ok := cachedData.(*ZabbixDatasourceInstance); ok {
zabbixURLStr := dsInfo.URL cachedDSHash := HashDatasourceInfo(cachedDS.dsInfo)
zabbixURL, err := url.Parse(zabbixURLStr) if cachedDSHash == dsInfoHash {
return cachedDS, nil
}
ds.logger.Debug("Data source settings changed", "org", pluginContext.OrgID, "id", dsSettings.ID, "name", dsSettings.Name)
}
}
ds.logger.Debug("Initializing data source", "org", pluginContext.OrgID, "id", dsSettings.ID, "name", dsSettings.Name)
dsInstance, err := NewZabbixDatasourceInstance(pluginContext.DataSourceInstanceSettings)
if err != nil { if err != nil {
ds.logger.Error("Error initializing datasource", "error", err)
return nil, err return nil, err
} }
zabbixAPI, err := zabbixapi.New(dsInfo.URL) ds.datasourceCache.Set(dsKey, dsInstance)
if err != nil { return dsInstance, nil
return nil, err
}
zabbixSettings, err := readZabbixSettings(dsInfo)
if err != nil {
return nil, err
}
return &ZabbixDatasourceInstance{
zabbixAPI: zabbixAPI,
url: zabbixURL,
dsInfo: dsInfo,
Settings: zabbixSettings,
queryCache: NewCache(zabbixSettings.CacheTTL, 10*time.Minute),
httpClient: &http.Client{
Transport: &http.Transport{
TLSClientConfig: &tls.Config{
Renegotiation: tls.RenegotiateFreelyAsClient,
},
Proxy: http.ProxyFromEnvironment,
Dial: (&net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
}).Dial,
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
MaxIdleConns: 100,
IdleConnTimeout: 90 * time.Second,
},
Timeout: time.Duration(time.Second * 30),
},
}, nil
} }
func readZabbixSettings(dsInstanceSettings *backend.DataSourceInstanceSettings) (*ZabbixDatasourceSettings, error) { func readZabbixSettings(dsInstanceSettings *backend.DataSourceInstanceSettings) (*ZabbixDatasourceSettings, error) {
zabbixSettingsDTO := &ZabbixDatasourceSettingsDTO{ zabbixSettingsDTO := &ZabbixDatasourceSettingsDTO{}
TrendsFrom: "7d",
TrendsRange: "4d",
CacheTTL: "1h",
}
err := json.Unmarshal(dsInstanceSettings.JSONData, &zabbixSettingsDTO) err := json.Unmarshal(dsInstanceSettings.JSONData, &zabbixSettingsDTO)
if err != nil { if err != nil {
@@ -207,32 +178,3 @@ func readZabbixSettings(dsInstanceSettings *backend.DataSourceInstanceSettings)
return zabbixSettings, nil return zabbixSettings, nil
} }
// GetDatasource Returns cached datasource or creates new one
func (ds *ZabbixDatasource) GetDatasource(pluginContext backend.PluginContext) (*ZabbixDatasourceInstance, error) {
dsSettings := pluginContext.DataSourceInstanceSettings
dsInfoHash := HashDatasourceInfo(dsSettings)
if cachedData, ok := ds.datasourceCache.Get(dsInfoHash); ok {
if cachedDS, ok := cachedData.(*ZabbixDatasourceInstance); ok {
return cachedDS, nil
}
}
ds.logger.Debug(fmt.Sprintf("Datasource cache miss (Org %d Id %d '%s' %s)", pluginContext.OrgID, dsSettings.ID, dsSettings.Name, dsInfoHash))
dsInstance, err := ds.NewZabbixDatasource(pluginContext.DataSourceInstanceSettings)
if err != nil {
ds.logger.Error("Error initializing datasource", "error", err)
return nil, err
}
ds.datasourceCache.Set(dsInfoHash, dsInstance)
return dsInstance, nil
}
func BuildAPIResponse(responseData *interface{}) (*ZabbixAPIResourceResponse, error) {
return &ZabbixAPIResourceResponse{
Result: *responseData,
}, nil
}

View File

@@ -97,102 +97,3 @@ func ReadQuery(query backend.DataQuery) (QueryModel, error) {
model.TimeRange = query.TimeRange model.TimeRange = query.TimeRange
return model, nil return model, nil
} }
// Old models
type connectionTestResponse struct {
ZabbixVersion string `json:"zabbixVersion"`
DbConnectorStatus *dbConnectionStatus `json:"dbConnectorStatus"`
}
type dbConnectionStatus struct {
DsType string `json:"dsType"`
DsName string `json:"dsName"`
}
type requestModel struct {
Target queryRequest `json:"target,omitempty"`
}
type queryRequest struct {
Method string `json:"method,omitempty"`
Params ZabbixAPIParams `json:"params,omitempty"`
}
type zabbixParamOutput struct {
Mode string
Fields []string
}
func (p *zabbixParamOutput) MarshalJSON() ([]byte, error) {
if p.Mode != "" {
return json.Marshal(p.Mode)
}
return json.Marshal(p.Fields)
}
func (p *zabbixParamOutput) UnmarshalJSON(data []byte) error {
if p == nil {
return fmt.Errorf("zabbixParamOutput: UnmarshalJSON on nil pointer")
}
var strArray []string
err := json.Unmarshal(data, &strArray)
if err == nil {
p.Fields = strArray
return nil
}
var str string
err = json.Unmarshal(data, &str)
if err == nil {
p.Mode = str
return nil
}
return fmt.Errorf("Unsupported type: %w", err)
}
type ZabbixAPIParamsLegacy struct {
Output *zabbixParamOutput `json:"output,omitempty"`
SortField string `json:"sortfield,omitempty"`
SortOrder string `json:"sortorder,omitempty"`
Filter map[string]interface{} `json:"filter,omitempty"`
// Login
User string `json:"user,omitempty"`
Password string `json:"password,omitempty"`
// Item GET
WebItems bool `json:"webitems,omitempty"`
SelectHosts interface{} `json:"selectHosts,omitempty"`
ItemIDs []string `json:"itemids,omitempty"`
GroupIDs []string `json:"groupids,omitempty"`
HostIDs []string `json:"hostids,omitempty"`
AppIDs []string `json:"applicationids,omitempty"`
// event.get
SelectAcknowledges interface{} `json:"select_acknowledges,omitempty"`
ObjectIDs []string `json:"objectids,omitempty"`
Value interface{} `json:"value,omitempty"`
// trigger.get
ExpandDescription bool `json:"expandDescription,omitempty"`
ExpandData bool `json:"expandData,omitempty"`
ExpandComment bool `json:"expandComment,omitempty"`
Monitored bool `json:"monitored,omitempty"`
SkipDependent bool `json:"skipDependent,omitempty"`
SelectLastEvent interface{} `json:"selectLastEvent,omitempty"`
// Host Group GET
RealHosts bool `json:"real_hosts,omitempty"`
// History GET
History *int `json:"history,omitempty,string"`
// History/Trends GET
TimeFrom int64 `json:"time_from,omitempty"`
TimeTill int64 `json:"time_till,omitempty"`
}

View File

@@ -60,6 +60,12 @@ func (ds *ZabbixDatasourceInstance) ZabbixAPIQuery(ctx context.Context, apiReq *
return BuildAPIResponse(&result) return BuildAPIResponse(&result)
} }
func BuildAPIResponse(responseData *interface{}) (*ZabbixAPIResourceResponse, error) {
return &ZabbixAPIResourceResponse{
Result: *responseData,
}, nil
}
// TestConnection checks authentication and version of the Zabbix API and returns that info // TestConnection checks authentication and version of the Zabbix API and returns that info
func (ds *ZabbixDatasourceInstance) TestConnection(ctx context.Context) (string, error) { func (ds *ZabbixDatasourceInstance) TestConnection(ctx context.Context) (string, error) {
_, err := ds.getAllGroups(ctx) _, err := ds.getAllGroups(ctx)

View File

@@ -1,8 +1,15 @@
package zabbixapi package zabbixapi
import "encoding/json"
type ZabbixAPIRequest struct { type ZabbixAPIRequest struct {
Method string `json:"method"` Method string `json:"method"`
Params ZabbixAPIParams `json:"params,omitempty"` Params ZabbixAPIParams `json:"params,omitempty"`
} }
func (r *ZabbixAPIRequest) String() string {
jsonRequest, _ := json.Marshal(r.Params)
return r.Method + string(jsonRequest)
}
type ZabbixAPIParams = map[string]interface{} type ZabbixAPIParams = map[string]interface{}