From 7ccf690c1c1ef05dcd00c614640d5b6b01eb26af Mon Sep 17 00:00:00 2001 From: Dmitrijs Goloscapovs Date: Wed, 11 Dec 2024 18:18:48 +0200 Subject: [PATCH] .......... [ZBX-25725] added debug, updated go-ole and sys --- src/go/go.mod | 4 +- src/go/go.sum | 10 ++-- src/go/internal/agent/scheduler/task.go | 35 +++++++++++++- src/go/pkg/wmi/wmi.go | 62 +++++++++++++++++++++---- src/go/pkg/zbxlib/nextcheck.go | 7 +++ src/go/plugins/windows/wmi/wmi.go | 3 ++ 6 files changed, 102 insertions(+), 19 deletions(-) diff --git a/src/go/go.mod b/src/go/go.mod index 40fabd22c45..8caf8188e8d 100644 --- a/src/go/go.mod +++ b/src/go/go.mod @@ -12,7 +12,7 @@ require ( github.com/eclipse/paho.mqtt.golang v1.4.2 github.com/fsnotify/fsnotify v1.5.4 github.com/go-ldap/ldap v3.0.3+incompatible - github.com/go-ole/go-ole v1.2.6 + github.com/go-ole/go-ole v1.3.0 github.com/go-sql-driver/mysql v1.7.1 github.com/goburrow/modbus v0.1.0 github.com/godbus/dbus/v5 v5.1.0 @@ -26,7 +26,7 @@ require ( github.com/sokurenko/go-netstat v1.0.0 golang.org/x/net v0.30.0 golang.org/x/sync v0.8.0 - golang.org/x/sys v0.26.0 + golang.org/x/sys v0.28.0 golang.org/x/text v0.19.0 golang.zabbix.com/sdk v1.2.2-0.20240905084005-af85407722b5 ) diff --git a/src/go/go.sum b/src/go/go.sum index 3e80c9702f1..3cee069fdba 100644 --- a/src/go/go.sum +++ b/src/go/go.sum @@ -24,8 +24,8 @@ github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNV github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0= github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= -github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= +github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= github.com/go-sql-driver/mysql v1.7.1 h1:lUIinVbN1DY0xBg0eMOzmmtGoHwWBbvnWubQUrtU8EI= github.com/go-sql-driver/mysql v1.7.1/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= github.com/goburrow/modbus v0.1.0 h1:DejRZY73nEM6+bt5JSP6IsFolJ9dVcqxsYbpLbeW/ro= @@ -81,12 +81,12 @@ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201207223542-d4d67f95c62d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.26.0 h1:KHjCJyddX0LoSTb3J+vWpupP9p0oznkqVk/IfjymZbo= -golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA= +golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= diff --git a/src/go/internal/agent/scheduler/task.go b/src/go/internal/agent/scheduler/task.go index 5595eac68ae..1a6aa6b2ff1 100644 --- a/src/go/internal/agent/scheduler/task.go +++ b/src/go/internal/agent/scheduler/task.go @@ -190,6 +190,8 @@ func invokeExport(a plugin.Accessor, key string, params []string, ctx plugin.Con } func (t *exporterTask) perform(s Scheduler) { + log.Debugf("exporterTask perform got itemid %v %q", t.item.itemid, t.item.key) + // pass item key as parameter so it can be safely updated while task is being processed in its goroutine go func(itemkey string) { var result *plugin.Result @@ -201,7 +203,11 @@ func (t *exporterTask) perform(s Scheduler) { if key, params, err = itemutil.ParseKey(itemkey); err == nil { var ret interface{} + log.Debugf("invokeExport invoked for itemid %v key %q, err = %v", + t.item.itemid, itemkey, err) ret, err = invokeExport(t.plugin.impl, key, params, t) + log.Debugf("invokeExport finished for itemid %v key %q, err = %v", + t.item.itemid, itemkey, err) if err == nil { log.Debugf("executed exporter task for itemid:%d key '%s'", t.item.itemid, itemkey) @@ -213,12 +219,18 @@ func (t *exporterTask) perform(s Scheduler) { case reflect.Array: s := reflect.ValueOf(ret) for i := 0; i < s.Len(); i++ { + log.Debugf("converting value to result for itemid:%d key %q", t.item.itemid, itemkey) result = itemutil.ValueToResult(t.item.itemid, now, s.Index(i).Interface()) + log.Debugf("writing result to output for itemid:%d key %q", t.item.itemid, itemkey) t.output.Write(result) + log.Debugf("wrote result to output for itemid:%d key %q", t.item.itemid, itemkey) } default: + log.Debugf("converting value to result for itemid:%d key %q", t.item.itemid, itemkey) result = itemutil.ValueToResult(t.item.itemid, now, ret) + log.Debugf("writing result to output for itemid:%d key %q", t.item.itemid, itemkey) t.output.Write(result) + log.Debugf("wrote result to output is done item id %v for key %q", t.item.itemid, itemkey) } } } else { @@ -228,7 +240,9 @@ func (t *exporterTask) perform(s Scheduler) { } if err != nil { result = &plugin.Result{Itemid: t.item.itemid, Error: err, Ts: now} + log.Debugf("writing result to output for itemid %v key %q", t.item.itemid, itemkey) t.output.Write(result) + log.Debugf("writing result to output is done for itemid %v key %q", t.item.itemid, itemkey) } // set failed state based on last result if result != nil && result.Error != nil { @@ -238,7 +252,13 @@ func (t *exporterTask) perform(s Scheduler) { t.failed = false } + log.Debugf("marking task as finished for itemid %v key %q", + t.item.itemid, itemkey) + s.FinishTask(t) + + log.Debugf("marked task as finished for itemid %v key %q", + t.item.itemid, itemkey) }(t.item.key) } @@ -332,6 +352,7 @@ func (t *directExporterTask) invokeExport(key string, params []string) (any, err } func (t *directExporterTask) perform(s Scheduler) { + log.Debugf("directExporterTask perform got itemid %v %q", t.item.itemid, t.item.key) // pass item key as parameter so it can be safely updated while task is being processed in its goroutine go func(itemkey string) { var result *plugin.Result @@ -342,27 +363,37 @@ func (t *directExporterTask) perform(s Scheduler) { if now.After(t.expire) { err = errors.New("Timeout while waiting for item in queue.") - log.Debugf("direct exporter task expired for key '%s' error: '%s'", itemkey, err.Error()) } else { if key, params, err = itemutil.ParseKey(itemkey); err == nil { var ret interface{} - log.Debugf("executing direct exporter task for key '%s'", itemkey) + log.Debugf("executing direct exporter task for itemid %v key %q", + t.item.itemid, itemkey) ret, err = t.invokeExport(key, params) + log.Debugf("invokeExport finished for itemid %v key %q, err = %v", + t.item.itemid, itemkey, err) + if err == nil { + log.Debugf("invoked itemutil.ValueToResult for itemid %v key %q", t.item.itemid, itemkey) result = itemutil.ValueToResult(t.item.itemid, now, ret) + log.Debugf("writing result to output for itemid %v key %q", t.item.itemid, itemkey) t.output.Write(result) t.done = true + log.Debugf("writing result to output is done for itemid %v key %q", t.item.itemid, itemkey) } } } if err != nil { result = &plugin.Result{Itemid: t.item.itemid, Error: err, Ts: now} + log.Debugf("writing result to output for key %q", itemkey) t.output.Write(result) + log.Debugf("writing result to output is done for key %q", itemkey) t.done = true } + log.Debugf("marking task as finished for key %q", itemkey) s.FinishTask(t) + log.Debugf("marked task as finished for key %q", itemkey) }(t.item.key) } diff --git a/src/go/pkg/wmi/wmi.go b/src/go/pkg/wmi/wmi.go index fa0d91ab00d..48a3b032679 100644 --- a/src/go/pkg/wmi/wmi.go +++ b/src/go/pkg/wmi/wmi.go @@ -248,45 +248,87 @@ func (r *tableResult) write(rs *ole.IDispatch) (err error) { } func performQuery(namespace string, query string, w resultWriter) (err error) { + log.Debugf("locking osthread") runtime.LockOSThread() - defer runtime.UnlockOSThread() + defer func() { + log.Debugf("defer for osthr, unlocking osthread") + runtime.UnlockOSThread() + log.Debugf("defer for osthr, unlocked osthread") + }() + + log.Debugf("ole.CoInitializeEx()") if oleErr := ole.CoInitializeEx(0, ole.COINIT_MULTITHREADED); oleErr != nil { oleCode := oleErr.(*ole.OleError).Code() if oleCode != ole.S_OK && oleCode != S_FALSE { return oleErr } } - defer ole.CoUninitialize() + defer func() { + log.Debugf("defer for CoInitializeEx, ole.CoUninitialize()") + ole.CoUninitialize() + log.Debugf("defer for CoInitializeEx, ole.CoUninitialize() done") + }() + log.Debugf("CreateObject WbemScripting.SWbemLocator") unknown, err := oleutil.CreateObject("WbemScripting.SWbemLocator") + log.Debugf("CreateObject WbemScripting.SWbemLocator done, err = %v", err) if err != nil { return } if unknown == nil { return errors.New("Cannot create SWbemLocator object.") } - defer unknown.Release() + defer func() { + log.Debugf("defer for CreateObject, releasing SWbemLocator") + unknown.Release() + log.Debugf("defer for CreateObject, released SWbemLocator") + }() + log.Debugf("calling QueryInterface()") disp, err := unknown.QueryInterface(ole.IID_IDispatch) + log.Debugf("called QueryInterface(), err = %v", err) if err != nil { return } - defer disp.Release() + defer func() { + log.Debugf("defer for QueryInterface() releasing disp") + disp.Release() + log.Debugf("defer for QueryInterface() released disp") + }() + log.Debugf("calling ConnectServer()") raw, err := oleutil.CallMethod(disp, "ConnectServer", nil, namespace) + log.Debugf("called ConnectServer(), err = %v", err) if err != nil { return } service := raw.ToIDispatch() - defer raw.Clear() - - if raw, err = oleutil.CallMethod(service, "ExecQuery", query); err != nil { + defer func() { + log.Debugf("defer raw.Clear()->ConnectServer") + raw.Clear() + log.Debugf("defer raw.Clear()->ConnectServer") + }() + + log.Debugf("calling ExecQuery()") + raw, err = oleutil.CallMethod(service, "ExecQuery", query) + log.Debugf("called ExecQuery(), err = %v", err) + if err != nil { return } + log.Debugf("converting variant to dispatch obj") result := raw.ToIDispatch() - defer raw.Clear() - - return w.write(result) + log.Debugf("converted variant to dispatch obj") + defer func() { + log.Debugf("defer raw.Clear()->CallMethod") + raw.Clear() + log.Debugf("defer raw.Clear()->CallMethod") + }() + + log.Debugf("writing object to resultWriter") + err = w.write(result) + log.Debugf("writing object to resultWriter done") + + return err } // QueryValue returns the value of the first column of the first row returned by the query. diff --git a/src/go/pkg/zbxlib/nextcheck.go b/src/go/pkg/zbxlib/nextcheck.go index 3f93e559161..fbfd2d541ca 100644 --- a/src/go/pkg/zbxlib/nextcheck.go +++ b/src/go/pkg/zbxlib/nextcheck.go @@ -21,6 +21,7 @@ package zbxlib int zbx_get_agent_item_nextcheck(zbx_uint64_t itemid, const char *delay, int now, int *nextcheck, int *scheduling, char **error); + */ import "C" @@ -46,9 +47,12 @@ func GetNextcheck(itemid uint64, delay string, from time.Time) (nextcheck time.T var cnextcheck, cscheduling C.int var cerr *C.char + log.Infof("In GetNextcheck, delay = %q", delay) cdelay := C.CString(delay) + log.Infof("In GetNextcheck after alloc cdelay ptr = %p", unsafe.Pointer(cdelay)) defer func() { log.Tracef("Calling C function \"free(cdelay)\"") + log.Infof("In GetNextcheck in defer before free cdelay ptr = %p", unsafe.Pointer(cdelay)) C.free(unsafe.Pointer(cdelay)) }() @@ -57,9 +61,12 @@ func GetNextcheck(itemid uint64, delay string, from time.Time) (nextcheck time.T ret := C.zbx_get_agent_item_nextcheck(C.zbx_uint64_t(itemid), cdelay, C.int(now), &cnextcheck, &cscheduling, &cerr) + log.Infof("In GetNextcheck after zbx_get_agent_item_nextcheck call, cdelay ptr = %p, cerr = %p", unsafe.Pointer(cdelay), unsafe.Pointer(cerr)) + if ret != Succeed { err = errors.New(C.GoString(cerr)) log.Tracef("Calling C function \"free()\"") + log.Infof("In GetNextcheck before free cerr = %p", unsafe.Pointer(cerr)) C.free(unsafe.Pointer(cerr)) } else { nextcheck = time.Unix(int64(cnextcheck), 0) diff --git a/src/go/plugins/windows/wmi/wmi.go b/src/go/plugins/windows/wmi/wmi.go index a6aece8c2b5..9a243d57da6 100644 --- a/src/go/plugins/windows/wmi/wmi.go +++ b/src/go/plugins/windows/wmi/wmi.go @@ -20,6 +20,7 @@ import ( "golang.zabbix.com/agent2/pkg/wmi" "golang.zabbix.com/sdk/errs" + "golang.zabbix.com/sdk/log" "golang.zabbix.com/sdk/plugin" ) @@ -70,7 +71,9 @@ func (p *Plugin) Export(key string, params []string, ctx plugin.ContextProvider) return wmiFmtAdapter(value), err case "wmi.getall": + log.Debugf("querying value %v->%v for itemid %v", params[0], params[1], ctx.ItemID()) m, err := wmi.QueryTable(params[0], params[1]) + log.Debugf("qry done for itemid %v", ctx.ItemID()) if err != nil { return nil, err } -- 2.39.2