# New community beat Perfmonbeat

**URL:** <https://discuss.elastic.co/t/new-community-beat-perfmonbeat/70688>\
**Category:** Beats\
**Created:** [January 5, 2017, 2:34pm UTC](https://discuss.elastic.co/t/new-community-beat-perfmonbeat/70688 "2017-01-05T14:34:28Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![maddin2016](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/maddin2016/32/16599_2.png) [@maddin2016](https://discuss.elastic.co/u/maddin2016)\
**Post date:** [January 5, 2017, 2:34pm UTC](https://discuss.elastic.co/t/new-community-beat-perfmonbeat/70688/1 "2017-01-05T14:34:28Z")

</div>

Hi @all,

i would like to show you a new community beat i created. It's called Perfmonbeat and it is a beat to collect perfomance counters from windows. It's yet very basic and there is a lot more to do ( exception handling, configs, naming of outputs, ...). But i want to discuss with you if it goes in the right direction and if there is a need for such a beat.

See [here](https://github.com/maddin2016/perfmonbeat)

BG

Martin

---

<div class="post-metadata">

**Author:** ![andrewkroh](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/andrewkroh/32/3784_2.png) [@andrewkroh](https://discuss.elastic.co/u/andrewkroh)\
**Post date:** [January 5, 2017, 7:05pm UTC](https://discuss.elastic.co/t/new-community-beat-perfmonbeat/70688/2 "2017-01-05T19:05:18Z")

</div>

I definitely like the idea of collecting perf data through the PDH API.

It looks like this would work nicely as a MetricSet in Metricbeat. Instead of using the beat generator there is a [metricset generator](https://github.com/elastic/beats/tree/master/generate/metricbeat/metricset) that creates a standalone beat using Metricbeat as a framework. Then you would have a MetricSet that could be later integrated into Metricbeat or be used as a [plugin](https://github.com/elastic/beats/pull/3217).

I didn't review the code since it's a work in progress. But one thing you should consider doing is generating code for the methods you need in the PDH API (here's a [place](https://github.com/elastic/gosigar/blob/master/sys/windows/syscall_windows.go#L364-L367) where we do that in gosigar). It uses the [mksyscall\_windows](https://github.com/golang/go/blob/release-branch.go1.7/src/syscall/mksyscall_windows.go) tool from Go.

And if you require constants from header files you can do some generation there too. You would create a `defs_windows.go` file that contains cgo code then run a generator to build another go file. See [defs\_windows.go](https://github.com/golang/go/blob/2058511e4e5966a7d482beb6033c68e324aa09ac/src/runtime/defs_windows.go#L5-L12).

This makes the code a little cleaner and means that you don't need to use cgo for your builds which then allows for easier cross-compiles.

---

<div class="post-metadata">

**Author:** ![maddin2016](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/maddin2016/32/16599_2.png) [@maddin2016](https://discuss.elastic.co/u/maddin2016)\
**Post date:** [January 5, 2017, 10:28pm UTC](https://discuss.elastic.co/t/new-community-beat-perfmonbeat/70688/3 "2017-01-05T22:28:22Z")

</div>

Hi @andrewkroh, many thanks for that detailed answer!! Especially for that part with cgo!! Really exciting stuff 😮 I also think it is better to create this as a MetricSet. I just wanted to start with coding. I create a new metricset an come back if i'm done.

---

<div class="post-metadata">

**Author:** ![maddin2016](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/maddin2016/32/16599_2.png) [@maddin2016](https://discuss.elastic.co/u/maddin2016)\
**Post date:** [January 9, 2017, 10:50am UTC](https://discuss.elastic.co/t/new-community-beat-perfmonbeat/70688/4 "2017-01-09T10:50:25Z")

</div>

Hi @andrewkroh, i have create a new repo to build a MetricSet instead of a beat. Now i'm try to configure config settings for that metricset. Assume the following structure i created

```auto
-module
    -windows
        -_meta
        - perfmon
            -_meta
                data.json
                fields.yaml
            perfmon.go

```

`windows` is my module and `perfmon` my metricset. Where i can add config only for that metricset  
e.g.

```auto
- module: windows
  metricsets: ["perfmon"]
  enabled: true
  period: 1s
  hosts: ["localhost"]
  perfmon.counters:  
    - alias: "Prozessorzeit"
      query: "\\Prozessorinformationen(*)\\Prozessorzeit (%)"

```

---

<div class="post-metadata">

**Author:** ![maddin2016](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/maddin2016/32/16599_2.png) [@maddin2016](https://discuss.elastic.co/u/maddin2016)\
**Post date:** [January 9, 2017, 1:22pm UTC](https://discuss.elastic.co/t/new-community-beat-perfmonbeat/70688/5 "2017-01-09T13:22:08Z")

</div>

I have found it in the [documentation](https://www.elastic.co/guide/en/beats/metricbeat/current/metricset-details.html)

---

<div class="post-metadata">

**Author:** ![maddin2016](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/maddin2016/32/16599_2.png) [@maddin2016](https://discuss.elastic.co/u/maddin2016)\
**Post date:** [January 10, 2017, 10:29am UTC](https://discuss.elastic.co/t/new-community-beat-perfmonbeat/70688/6 "2017-01-10T10:29:05Z")

</div>

Hi @andrewkroh, i have created file `defs_windows.go` with the following content

```auto
package perfmon

/*
#include <windows.h>
#include <stdio.h>
#include <conio.h>
#include <pdh.h>
#include <pdhmsg.h>
#cgo LDFLAGS: -lpdh
*/
import "C"

const (
	ERROR_SUCESS = C.ERROR_SUCCESS
	PDH_STATUS_VALID_DATA = C.PDH_CSTATUS_VALID_DATA
	PDH_STATUS_NEW_DATA = C.PDH_CSTATUS_NEW_DATA
	PDH_NO_DATA = C.PDH_NO_DATA
	PDH_STATUS_NO_OBJECT = C.PDH_CSTATUS_NO_OBJECT
	PDH_STATUS_NO_COUNTER = C.PDH_CSTATUS_NO_COUNTER
	PDH_STATUS_INVALID_DATA = C.PDH_CSTATUS_INVALID_DATA
	PDH_INVALID_HANDLE = C.PDH_INVALID_HANDLE
	PDH_INVALID_DATA = C.PDH_INVALID_DATA
	PDH_NO_MORE_DATA = C.PDH_NO_MORE_DATA
	PdhFmtDouble = C.PDH_FMT_DOUBLE
	PdhFmtLarge = C.PDH_FMT_LARGE
	PdhFmtLong = C.PDH_FMT_LONG
)

type PdhCounterValue C.PDH_FMT_COUNTERVALUE

```

i then call `go tool cgo -godefs defs_windows.go > defs_windows_amd64.go` which creates this output

```auto
// Created by cgo -godefs - DO NOT EDIT
// cgo.exe -godefs defs_windows.go

package perfmon

const (
	ERROR_SUCESS = 0x0
	PDH_STATUS_VALID_DATA	= 0x0
	PDH_STATUS_NEW_DATA	= 0x1
	PDH_NO_DATA = 0x800007d5
	PDH_STATUS_NO_OBJECT	= 0xc0000bb8
	PDH_STATUS_NO_COUNTER	= 0xc0000bb9
	PDH_STATUS_INVALID_DATA	= 0xc0000bba
	PDH_INVALID_HANDLE	= 0xc0000bbc
	PDH_INVALID_DATA	= 0xc0000bc6
	PDH_NO_MORE_DATA	= 0xc0000bcc
	PdhFmtDouble = 0x200
	PdhFmtLarge = 0x400
	PdhFmtLong = 0x100
)

type PdhCounterValue struct {
	CStatus uint32
	Pad_cgo_0	[4]byte
	LongValue	int32
	Pad_cgo_1	[4]byte
}

```

But if i then call `go build` or `go generate` i get this error `\perfmon\defs_windows_amd64.go: unexpected NUL in input`. Any ideas??

---

<div class="post-metadata">

**Author:** ![andrewkroh](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/andrewkroh/32/3784_2.png) [@andrewkroh](https://discuss.elastic.co/u/andrewkroh)\
**Post date:** [January 10, 2017, 10:58am UTC](https://discuss.elastic.co/t/new-community-beat-perfmonbeat/70688/7 "2017-01-10T10:58:22Z")

</div>

Do you have a `// +build ignore` at the top of the `defs_windows.go` file?

---

<div class="post-metadata">

**Author:** ![maddin2016](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/maddin2016/32/16599_2.png) [@maddin2016](https://discuss.elastic.co/u/maddin2016)\
**Post date:** [January 10, 2017, 11:13am UTC](https://discuss.elastic.co/t/new-community-beat-perfmonbeat/70688/8 "2017-01-10T11:13:03Z")

</div>

Should that command be present in all def files? `defs_windows_amd64.go`, `defs_windows_386.go`. Is it necessary to create these `386, amd64` files or is it better to copy the output from the `cgo` command into `defs_windows.go` and just have this file? There is also one thing more 🙈 i created a wrapper `pdh_windows.go` like you say.

```auto
//go:generate go run $GOROOT/src/syscall/mksyscall_windows.go -output pdh_windows.go pdh.go
// Windows API calls
//sys _PdhOpenQuery(dataSource *string, userData int, query *syscall.Handle) (err int) = pdh.PdhOpenQuery
//sys _PdhAddCounter(query syscall.Handle, counterPath string, userData int, counter *syscall.Handle) (err int) = pdh.PdhAddCounter
//sys _PdhCollectQueryData(query syscall.Handle) (err int) = pdh.PdhCollectQueryData
//sys _PdhGetFormattedCounterValue(counter syscall.Handle, format int, counterType int, value PdhCounterValue) (err int) = pdh.GetFormattedCounterValue

```

This all works fine, except in the output file there is an import statement `"golang.org/x/sys/windows"`. which is used by `modpdh = windows.NewLazySystemDLL("pdh.dll")`. should i use `syscall` instead and then `modpdh = syscall.NewLazyDLL("pdh.dll")`??

Sorry for all that questions 😥

---

<div class="post-metadata">

**Author:** ![andrewkroh](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/andrewkroh/32/3784_2.png) [@andrewkroh](https://discuss.elastic.co/u/andrewkroh)\
**Post date:** [January 10, 2017, 11:35am UTC](https://discuss.elastic.co/t/new-community-beat-perfmonbeat/70688/9 "2017-01-10T11:35:34Z")

</div>

defs\_windows.go is the source file for generating defs\_windows\_amd64.go and defs\_windows\_386.go. All three files should be committed to your repo. defs\_windows.go will not be used by `go build` so it needs to have the build tag so that the compiler ignore it. Doing this allows us to build without needing cgo. cgo is only needed if we have to change defs\_windows.go and need to regenerate defs\_windows\_amd64.go and defs\_windows\_386.go.

> [@maddin2016](#):
>
> This all works fine, except in the output file

What "output" file? The code generated by `mksyscall_windows.go` should have imports for `syscall` and not `windows`.

---

<div class="post-metadata">

**Author:** ![maddin2016](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/maddin2016/32/16599_2.png) [@maddin2016](https://discuss.elastic.co/u/maddin2016)\
**Post date:** [January 10, 2017, 11:41am UTC](https://discuss.elastic.co/t/new-community-beat-perfmonbeat/70688/10 "2017-01-10T11:41:50Z")

</div>

`pdh_windows.go`. This is the generated file from `mksyscall_windows.go`. There is an import for `windows`. Maybe a bug or and old version??

---

<div class="post-metadata">

**Author:** ![andrewkroh](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/andrewkroh/32/3784_2.png) [@andrewkroh](https://discuss.elastic.co/u/andrewkroh)\
**Post date:** [January 10, 2017, 11:51am UTC](https://discuss.elastic.co/t/new-community-beat-perfmonbeat/70688/11 "2017-01-10T11:51:42Z")

</div>

It looks like it does have logic for the [golang.org/x/sys/windows](http://golang.org/x/sys/windows) package. [https://golang.org/src/syscall/mksyscall\_windows.go#L741](https://golang.org/src/syscall/mksyscall_windows.go#L741) I didn't examine the logic, but I would prefer functions in the `syscall` package over `golang.org/x/sys/windows` if you have a choice (just to reduce the external deps). But if there's a function in the windows package that makes life easier use it.

---

<div class="post-metadata">

**Author:** ![maddin2016](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/maddin2016/32/16599_2.png) [@maddin2016](https://discuss.elastic.co/u/maddin2016)\
**Post date:** [January 10, 2017, 12:00pm UTC](https://discuss.elastic.co/t/new-community-beat-perfmonbeat/70688/12 "2017-01-10T12:00:55Z")

</div>

Ok, i will use the `syscall` package. [Here](https://github.com/maddin2016/pdhbeat/tree/master/module/windows/perfmon) are the new metricset i have created (ignore the name of the beat). There is only that error with `unexpteced NUL` in `defs_windows_amd64.go`. Maybe you have some time to look over. I can't see whats wrong with this file 😕

---

<div class="post-metadata">

**Author:** ![andrewkroh](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/andrewkroh/32/3784_2.png) [@andrewkroh](https://discuss.elastic.co/u/andrewkroh)\
**Post date:** [January 10, 2017, 12:05pm UTC](https://discuss.elastic.co/t/new-community-beat-perfmonbeat/70688/13 "2017-01-10T12:05:42Z")

</div>

Where's the error coming from?

It builds for me:

```auto
$ pwd
/Users/akroh/go/src/github.com/maddin2016/pdhbeat/module/windows
$ GOOS=windows GOARCH=amd64 go build; echo $?
0

```

---

<div class="post-metadata">

**Author:** ![maddin2016](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/maddin2016/32/16599_2.png) [@maddin2016](https://discuss.elastic.co/u/maddin2016)\
**Post date:** [January 10, 2017, 12:11pm UTC](https://discuss.elastic.co/t/new-community-beat-perfmonbeat/70688/14 "2017-01-10T12:11:17Z")

</div>

That error comes if i'm trying to build on windows.

---

<div class="post-metadata">

**Author:** ![maddin2016](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/maddin2016/32/16599_2.png) [@maddin2016](https://discuss.elastic.co/u/maddin2016)\
**Post date:** [January 10, 2017, 12:18pm UTC](https://discuss.elastic.co/t/new-community-beat-perfmonbeat/70688/15 "2017-01-10T12:18:55Z")

</div>

Ohh, got it. This error throws if you are in the wrong folder. I tried `go build` in `maddin2016/pdhbeat` instead of `maddin2016\pdhbeat\module\windows`. How can i test if the new metricset is working? Do i have to build the whole metricbeat?

---

<div class="post-metadata">

**Author:** ![andrewkroh](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/andrewkroh/32/3784_2.png) [@andrewkroh](https://discuss.elastic.co/u/andrewkroh)\
**Post date:** [January 10, 2017, 12:34pm UTC](https://discuss.elastic.co/t/new-community-beat-perfmonbeat/70688/16 "2017-01-10T12:34:27Z")

</div>

> [@maddin2016](#):
>
> How can i test if the new metricset is working? Do i have to build the whole metricbeat?

`go build` in [GitHub - martinscholz83/pdhbeat](http://github.com/maddin2016/pdhbeat) will produce `pdhbeat.exe` that you can use. If you uncomment this [line](https://github.com/maddin2016/pdhbeat/blob/master/main.go#L12-L15) you can use the the normal metricbeat modules too (the configuration will all be namespaced under pdhbeat instead of metricbeat).

> [@maddin2016](#):
>
> There is only that error with unexpteced NUL in defs\_windows\_amd64.go.

Check defs\_windows.go for bad characters. Run gofmt on it and gofmt on the output files too. I'm seeing bad encoding.

```auto
defs_windows_amd64.go:1:1: illegal UTF-8 encoding
defs_windows_amd64.go:1:1: illegal character U+FFFD '�'
defs_windows_amd64.go:1:2: illegal UTF-8 encoding

```

---

<div class="post-metadata">

**Author:** ![maddin2016](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/maddin2016/32/16599_2.png) [@maddin2016](https://discuss.elastic.co/u/maddin2016)\
**Post date:** [January 10, 2017, 12:49pm UTC](https://discuss.elastic.co/t/new-community-beat-perfmonbeat/70688/17 "2017-01-10T12:49:11Z")

</div>

It seems that the `go tool cgo` command add these characters. I had to explicit save the file as UTF-8 with notepad.

---

<div class="post-metadata">

**Author:** ![maddin2016](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/maddin2016/32/16599_2.png) [@maddin2016](https://discuss.elastic.co/u/maddin2016)\
**Post date:** [January 11, 2017, 12:11pm UTC](https://discuss.elastic.co/t/new-community-beat-perfmonbeat/70688/18 "2017-01-11T12:11:13Z")

</div>

Hi @andrewkroh, if you had the time can try to run this metricbeat on a windows machine. I had to do some fixing of types and add some errors. But basically it is running.

---

<div class="post-metadata">

**Author:** ![steffens](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/steffens/32/79630_2.png) [@steffens](https://discuss.elastic.co/u/steffens)\
**Post date:** [January 11, 2017, 12:51pm UTC](https://discuss.elastic.co/t/new-community-beat-perfmonbeat/70688/19 "2017-01-11T12:51:21Z")

</div>

@maddin2016 with go make sure your files are UTF-8 always. By default windows tools often use UTF16LE which might not parse well with utf-8.

---

<div class="post-metadata">

**Author:** ![maddin2016](https://sea2.discourse-cdn.com/elastic/user_avatar/discuss.elastic.co/maddin2016/32/16599_2.png) [@maddin2016](https://discuss.elastic.co/u/maddin2016)\
**Post date:** [January 11, 2017, 2:01pm UTC](https://discuss.elastic.co/t/new-community-beat-perfmonbeat/70688/20 "2017-01-11T14:01:05Z")

</div>

Yeap, comming from .NET UTF16 is the default if you not specify encoding.

[Next page](https://discuss.elastic.co/t/new-community-beat-perfmonbeat/70688.md?page=2)
