Skip to content

Commit

Permalink
feat: read header to determine num sensors/readings, large refactor t…
Browse files Browse the repository at this point in the history
…o improve clarity
  • Loading branch information
zachstence committed Jun 16, 2023
1 parent 0d52243 commit 75b9a65
Show file tree
Hide file tree
Showing 10 changed files with 255 additions and 300 deletions.
77 changes: 29 additions & 48 deletions plugins/inputs/hwinfo/hwinfo.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
package hwinfo

import (
"fmt"
"runtime/debug"
"strconv"
"strings"
Expand All @@ -13,50 +12,48 @@ import (
"github.com/influxdata/telegraf/plugins/inputs"
"github.com/rs/zerolog/log"

hwinfoInternal "github.com/zachstence/hwinfo-telegraf-plugin/plugins/inputs/hwinfo/internal"
shmem "github.com/zachstence/hwinfo-telegraf-plugin/plugins/inputs/hwinfo/hwinfoShMem"
)

// ============================================================================
// Public input plugin interface
// ============================================================================

type HWiNFOInput struct {
type HWiNFOInputPlugin struct {
hwinfoVersion string
pluginVersion string
shmemVersion string
}

func init() {
inputs.Add("hwinfo", func() telegraf.Input {
return &HWiNFOInput{
return &HWiNFOInputPlugin{
hwinfoVersion: HWiNFOVersion(),
pluginVersion: PluginVersion(),
shmemVersion: SHMemVersion(),
}
})
}

func (input *HWiNFOInput) Init() error {
func (input *HWiNFOInputPlugin) Init() error {
return nil
}

func (input *HWiNFOInput) Stop() {
// Make sure mutex is unlocked before stopping
hwinfoInternal.UnlockMutex()
func (input *HWiNFOInputPlugin) Stop() {
shmem.UnlockMutex()
}

func (input *HWiNFOInput) SampleConfig() string {
func (input *HWiNFOInputPlugin) SampleConfig() string {
return `
[[inputs.hwinfo]]
# no config
`
}

func (input *HWiNFOInput) Description() string {
func (input *HWiNFOInputPlugin) Description() string {
return "Gather Windows system hardware information from HWiNFO"
}

func (input *HWiNFOInput) Gather(a telegraf.Accumulator) error {
func (input *HWiNFOInputPlugin) Gather(a telegraf.Accumulator) error {
log.Debug().Msg("Gathering metrics...")

// Gather data
Expand Down Expand Up @@ -100,15 +97,6 @@ func PluginVersion() string {
return bi.Deps[i].Version
}

func SHMemVersion() string {
rawData, err := hwinfoInternal.Read()
if err != nil {
log.Fatal().Err(err).Send()
}

return fmt.Sprintf("v%d rev%d", rawData.Version(), rawData.Revision())
}

// ============================================================================
// Private helpers
// ============================================================================
Expand All @@ -119,51 +107,44 @@ type Metric struct {
}

type SensorReadings struct {
sensor hwinfoInternal.Sensor
readings []hwinfoInternal.Reading
sensor shmem.Sensor
readings []shmem.Reading
}

func (input *HWiNFOInput) gather() []SensorReadings {
rawData, err := hwinfoInternal.Read()
func (input *HWiNFOInputPlugin) gather() []SensorReadings {
rawData, err := shmem.Read()
if err != nil {
log.Fatal().Err(err).Send()
}
log.Debug().Msgf("Found %d sensors with a total of %d readings", rawData.NumSensorElements(), rawData.NumReadingElements())
input.shmemVersion = rawData.Version()

data := []SensorReadings{}

// Get sensors
for s := range rawData.IterSensors() {
if s.Error != nil {
log.Error().Err(s.Error).Send()
} else {
data = append(data, SensorReadings{
sensor: s.Sensor,
readings: []hwinfoInternal.Reading{},
})
}
for _, s := range rawData.Sensors() {
data = append(data, SensorReadings{
sensor: s,
readings: []shmem.Reading{},
})
}
log.Debug().Msgf("Processed %d sensors", rawData.NumSensorElements())
log.Debug().Msgf("Processed %d sensors", rawData.Header().NumSensorElements())

// Get readings
for r := range rawData.IterReadings() {
if r.Error != nil {
log.Error().Err(r.Error).Send()
} else {
sensorIndex := int(r.Reading.SensorIndex())
if sensorIndex < len(data) {
data[sensorIndex].readings = append(data[sensorIndex].readings, r.Reading)
} else {
log.Error().Msgf("sensor index out of range, attempting to access index %d, but %d sensors found ", sensorIndex, len(data))
}
for _, r := range rawData.Readings() {
sensorIndex := int(r.SensorIndex())
if sensorIndex >= len(data) {
log.Error().Msgf("sensor index out of range, attempting to access index %d, but %d sensors found ", sensorIndex, len(data))
continue
}

data[sensorIndex].readings = append(data[sensorIndex].readings, r)
}
log.Debug().Msgf("Processed %d readings", rawData.NumReadingElements())
log.Debug().Msgf("Processed %d readings", rawData.Header().NumReadingElements())

return data
}

func (hwinfo *HWiNFOInput) buildFieldsAndTags(sensorReadings SensorReadings) []Metric {
func (hwinfo *HWiNFOInputPlugin) buildFieldsAndTags(sensorReadings SensorReadings) []Metric {
metrics := []Metric{}

sensor := sensorReadings.sensor
Expand Down
71 changes: 71 additions & 0 deletions plugins/inputs/hwinfo/hwinfoShMem/header.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package hwinfoShMem

// #include "hwisenssm2.h"
import "C"

import (
"unsafe"
)

const headerLength = C.sizeof_HWiNFO_SENSORS_SHARED_MEM2

type Header struct {
c C.PHWiNFO_SENSORS_SHARED_MEM2
}

func NewHeader(data []byte) Header {
return Header{
c: C.PHWiNFO_SENSORS_SHARED_MEM2(unsafe.Pointer(&data[0])),
}
}

// Signature "HWiS" if active, 'DEAD' when inactive
func (header *Header) Signature() string {
return DecodeCharPtr(unsafe.Pointer(&header.c.dwSignature), C.sizeof_DWORD)
}

// Version version of shared memory
func (header *Header) Version() int {
return int(header.c.dwVersion)
}

// Revision revision of version
func (header *Header) Revision() int {
return int(header.c.dwRevision)
}

// PollTime last polling time
func (header *Header) PollTime() uint64 {
addr := unsafe.Pointer(uintptr(unsafe.Pointer(&header.c.dwRevision)) + C.sizeof_DWORD)
return uint64(*(*C.__time64_t)(addr))
}

// OffsetOfSensorSection offset of the Sensor section from beginning of HWiNFO_SENSORS_SHARED_MEM2
func (header *Header) OffsetOfSensorSection() int {
return int(header.c.dwOffsetOfSensorSection)
}

// SizeOfSensorElement size of each sensor element = sizeof( HWiNFO_SENSORS_SENSOR_ELEMENT )
func (header *Header) SizeOfSensorElement() int {
return int(header.c.dwSizeOfSensorElement)
}

// NumSensorElements number of sensor elements
func (header *Header) NumSensorElements() int {
return int(header.c.dwNumSensorElements)
}

// OffsetOfReadingSection offset of the Reading section from beginning of HWiNFO_SENSORS_SHARED_MEM2
func (header *Header) OffsetOfReadingSection() int {
return int(header.c.dwOffsetOfReadingSection)
}

// SizeOfReadingElement size of each Reading element = sizeof( HWiNFO_SENSORS_READING_ELEMENT )
func (header *Header) SizeOfReadingElement() int {
return int(header.c.dwSizeOfReadingElement)
}

// NumReadingElements number of Reading elements
func (header *Header) NumReadingElements() int {
return int(header.c.dwNumReadingElements)
}
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,21 +1,21 @@
package mutex
package hwinfoShMem

// #include "../hwisenssm2.h"
// #include "hwisenssm2.h"
import "C"
import (
"errors"
"fmt"
"sync"
"unsafe"

log "github.com/rs/zerolog/log"
"github.com/rs/zerolog/log"
)

var ghnd C.HANDLE
var imut = sync.Mutex{}

// Lock the global mutex
func Lock() {
func LockMutex() {
imut.Lock()
lpName := C.CString(C.HWiNFO_SENSORS_SM2_MUTEX)
defer C.free(unsafe.Pointer(lpName))
Expand All @@ -28,7 +28,7 @@ func Lock() {
}

// Unlock the global mutex
func Unlock() {
func UnlockMutex() {
defer imut.Unlock()
C.CloseHandle(ghnd)
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package hwinfo
package hwinfoShMem

/*
#include <windows.h>
Expand All @@ -7,8 +7,6 @@ package hwinfo
import "C"
import (
"unsafe"

"github.com/zachstence/hwinfo-telegraf-plugin/plugins/inputs/hwinfo/internal/util"
)

// ReadingType enum of value/unit type for reading
Expand Down Expand Up @@ -74,17 +72,17 @@ func (r *Reading) ReadingID() uint64 {

// LabelOrig original label (e.g. "Chassis2 Fan")
func (r *Reading) LabelOrig() string {
return util.DecodeCharPtr(unsafe.Pointer(&r.cr.szLabelOrig), C.HWiNFO_SENSORS_STRING_LEN2)
return DecodeCharPtr(unsafe.Pointer(&r.cr.szLabelOrig), C.HWiNFO_SENSORS_STRING_LEN2)
}

// LabelUser label displayed, which might have been renamed by user
func (r *Reading) LabelUser() string {
return util.DecodeCharPtr(unsafe.Pointer(&r.cr.szLabelUser), C.HWiNFO_SENSORS_STRING_LEN2)
return DecodeCharPtr(unsafe.Pointer(&r.cr.szLabelUser), C.HWiNFO_SENSORS_STRING_LEN2)
}

// Unit e.g. "RPM"
func (r *Reading) Unit() string {
return util.DecodeCharPtr(unsafe.Pointer(&r.cr.szUnit), C.HWiNFO_UNIT_STRING_LEN)
return DecodeCharPtr(unsafe.Pointer(&r.cr.szUnit), C.HWiNFO_UNIT_STRING_LEN)
}

func (r *Reading) valuePtr() unsafe.Pointer {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
package hwinfo
package hwinfoShMem

// #include "hwisenssm2.h"
import "C"

import (
"strconv"
"unsafe"

"github.com/zachstence/hwinfo-telegraf-plugin/plugins/inputs/hwinfo/internal/util"
)

// Sensor element (e.g. motherboard, cpu, gpu...)
Expand Down Expand Up @@ -55,34 +53,34 @@ func (s *Sensor) ID() string {

// NameOrig original name of sensor
func (s *Sensor) NameOrig() string {
return util.DecodeCharPtr(unsafe.Pointer(&s.cs.szSensorNameOrig), C.HWiNFO_SENSORS_STRING_LEN2)
return DecodeCharPtr(unsafe.Pointer(&s.cs.szSensorNameOrig), C.HWiNFO_SENSORS_STRING_LEN2)
}

// NameUser sensor name displayed, which might have been renamed by user
func (s *Sensor) NameUser() string {
return util.DecodeCharPtr(unsafe.Pointer(&s.cs.szSensorNameUser), C.HWiNFO_SENSORS_STRING_LEN2)
return DecodeCharPtr(unsafe.Pointer(&s.cs.szSensorNameUser), C.HWiNFO_SENSORS_STRING_LEN2)
}

// TODO I wish there was a better way to do this, ideally something provided explicitly bw HWiNFO
// A dynamic value computed by looking at other fields of the sensor
func (s *Sensor) SensorType() SensorType {
name := s.NameOrig()

if util.StartsWithLower(name, "system") {
if StartsWithLower(name, "system") {
return System
} else if util.StartsWithLower(name, "cpu") {
} else if StartsWithLower(name, "cpu") {
return CPU
} else if util.StartsWithLower(name, "s.m.a.r.t.") {
} else if StartsWithLower(name, "s.m.a.r.t.") {
return SMART
} else if util.StartsWithLower(name, "drive") {
} else if StartsWithLower(name, "drive") {
return Drive
} else if util.StartsWithLower(name, "gpu") {
} else if StartsWithLower(name, "gpu") {
return GPU
} else if util.StartsWithLower(name, "network") {
} else if StartsWithLower(name, "network") {
return Network
} else if util.StartsWithLower(name, "windows") {
} else if StartsWithLower(name, "windows") {
return Windows
} else if util.StartsWithLower(name, "memory timings") {
} else if StartsWithLower(name, "memory timings") {
return MemoryTimings
} else {
return Unknown
Expand Down
Loading

0 comments on commit 75b9a65

Please sign in to comment.