diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index d344f6f7..75a3e680 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -90,8 +90,8 @@ jobs: go-version-file: 'go.mod' - name: golangci-lint - uses: golangci/golangci-lint-action@55c2c1448f86e01eaae002a5a3a9624417608d84 # v6.5.2 + uses: golangci/golangci-lint-action@1481404843c368bc19ca9406f87d6e0fc97bdcfd # v7.0.0 with: # renovate: github=golangci/golangci-lint - version: v1.64.8 + version: v2.0.2 args: "--max-same-issues=0" diff --git a/.golangci.yaml b/.golangci.yaml index b1c9a9d6..d976070c 100644 --- a/.golangci.yaml +++ b/.golangci.yaml @@ -1,5 +1,6 @@ +version: "2" linters: - enable-all: true + default: all disable: - cyclop - depguard @@ -13,74 +14,93 @@ linters: - goconst - gocyclo - godot - - paralleltest - lll - maintidx - mnd + - paralleltest - testpackage - varnamelen - wrapcheck - -run: - timeout: 15m - -output: - sort-results: true - -linters-settings: - gosec: - excludes: - - G101 # Potential hardcoded credentials - - G115 # integer overflow conversion - - gci: - sections: - - prefix(github.com/prometheus-community/windows_exporter/internal/windowsservice) - - standard # Standard section: captures all standard packages. - - default # Default section: contains all imports that could not be matched to another section type. - custom-order: true - tagliatelle: - case: - use-field-name: true - rules: - # Any struct tag type can be used. - # Support string case: `camel`, `pascal`, `kebab`, `snake`, `upperSnake`, `goCamel`, `goPascal`, `goKebab`, `goSnake`, `upper`, `lower`, `header` - json: camel - yaml: snake - forbidigo: - forbid: - - "^(fmt\\.Print(|f|ln)|print|println)$" - - p: "^syscall\\.(.{1,7}|.{7}[^N]|.{9,})$" - msg: use golang.org/x/sys/windows instead of syscall - - p: "^windows\\.NewLazyDLL$" - msg: use NewLazySystemDLL instead NewLazyDLL - sloglint: - no-mixed-args: true - kv-only: false - attr-only: true - no-global: "all" - context: "scope" - static-msg: false - no-raw-keys: false - key-naming-case: snake - forbidden-keys: - - time - - level - - msg - - source - args-on-sep-lines: true - stylecheck: - checks: ["all", "-ST1003"] -issues: - exclude: - - don't use underscores in Go names - - don't use an underscore in package name - - exported type .+ should have comment or be unexported - exclude-rules: - - # Golint has many capitalisation complaints on WMI class names - text: "`?\\w+`? should be `?\\w+`?" - linters: - - revive - - text: "don't use ALL_CAPS in Go names; use CamelCase" - linters: - - revive + settings: + forbidigo: + forbid: + - pattern: ^(fmt\.Print(|f|ln)|print|println)$ + - pattern: ^syscall\.(.{1,7}|.{7}[^N]|.{9,})$ + msg: use golang.org/x/sys/windows instead of syscall + - pattern: ^windows\.NewLazyDLL$ + msg: use NewLazySystemDLL instead NewLazyDLL + gosec: + excludes: + - G101 + - G115 + sloglint: + no-mixed-args: true + kv-only: false + attr-only: true + no-global: all + context: scope + static-msg: false + no-raw-keys: false + key-naming-case: snake + forbidden-keys: + - time + - level + - msg + - source + args-on-sep-lines: true + staticcheck: + checks: + - -ST1003 + - all + tagliatelle: + case: + rules: + json: camel + yaml: snake + use-field-name: true + exclusions: + generated: lax + presets: + - comments + - common-false-positives + - legacy + - std-error-handling + rules: + - linters: + - revive + text: '`?\w+`? should be `?\w+`?' + - linters: + - revive + text: don't use ALL_CAPS in Go names; use CamelCase + - path: .+\.go$ + text: don't use underscores in Go names + - path: .+\.go$ + text: don't use an underscore in package name + - path: .+\.go$ + text: exported type .+ should have comment or be unexported + - linters: + - staticcheck + text: "ST1003:" + paths: + - third_party$ + - builtin$ + - examples$ +formatters: + enable: + - gci + - gofmt + - gofumpt + - goimports + settings: + gci: + sections: + - prefix(github.com/prometheus-community/windows_exporter/internal/windowsservice) + - standard + - default + custom-order: true + exclusions: + generated: lax + paths: + - third_party$ + - builtin$ + - examples$ diff --git a/internal/collector/exchange/exchange.go b/internal/collector/exchange/exchange.go index 13f2465b..f7b8b1ee 100644 --- a/internal/collector/exchange/exchange.go +++ b/internal/collector/exchange/exchange.go @@ -40,7 +40,7 @@ const ( subCollectorAutoDiscover = "Autodiscover" subCollectorWorkloadManagement = "WorkloadManagement" subCollectorRpcClientAccess = "RpcClientAccess" - subCollectorMapiHttpEmsmdb = "MapiHttpEmsmdb" + subCollectorMapiHTTPEmsmdb = "MapiHttpEmsmdb" ) type Config struct { @@ -59,7 +59,7 @@ var ConfigDefaults = Config{ subCollectorAutoDiscover, subCollectorWorkloadManagement, subCollectorRpcClientAccess, - subCollectorMapiHttpEmsmdb, + subCollectorMapiHTTPEmsmdb, }, } @@ -74,7 +74,7 @@ type Collector struct { collectorAutoDiscover collectorAvailabilityService collectorHTTPProxy - collectorMapiHttpEmsmdb + collectorMapiHTTPEmsMDB collectorOWA collectorRpcClientAccess collectorTransportQueues @@ -129,7 +129,7 @@ func NewWithFlags(app *kingpin.Application) *Collector { subCollectorAutoDiscover: "[29240] MSExchange Autodiscover", subCollectorWorkloadManagement: "[19430] MSExchange WorkloadManagement Workloads", subCollectorRpcClientAccess: "[29336] MSExchange RpcClientAccess", - subCollectorMapiHttpEmsmdb: "[26463] MSExchange MapiHttp Emsmdb", + subCollectorMapiHTTPEmsmdb: "[26463] MSExchange MapiHttp Emsmdb", } sb := strings.Builder{} @@ -219,10 +219,10 @@ func (c *Collector) Build(_ *slog.Logger, _ *mi.Session) error { collect: c.collectRpcClientAccess, close: c.perfDataCollectorRpcClientAccess.Close, }, - subCollectorMapiHttpEmsmdb: { - build: c.buildMapiHttpEmsmdb, - collect: c.collectMapiHttpEmsmdb, - close: c.perfDataCollectorMapiHttpEmsmdb.Close, + subCollectorMapiHTTPEmsmdb: { + build: c.buildMapiHTTPEmsMDB, + collect: c.collectMapiHTTPEmsMDB, + close: c.perfDataCollectorMapiHTTPEmsMDB.Close, }, } diff --git a/internal/collector/exchange/exchange_mapi_http_emsmdb.go b/internal/collector/exchange/exchange_mapi_http_emsmdb.go index 817687a7..f7420dcf 100644 --- a/internal/collector/exchange/exchange_mapi_http_emsmdb.go +++ b/internal/collector/exchange/exchange_mapi_http_emsmdb.go @@ -23,26 +23,26 @@ import ( "github.com/prometheus/client_golang/prometheus" ) -type collectorMapiHttpEmsmdb struct { - perfDataCollectorMapiHttpEmsmdb *pdh.Collector - perfDataObjectMapiHttpEmsmdb []perfDataCounterValuesMapiHttpEmsmdb +type collectorMapiHTTPEmsMDB struct { + perfDataCollectorMapiHTTPEmsMDB *pdh.Collector + perfDataObjectMapiHTTPEmsMDB []perfDataCounterValuesMapiHTTPEmsMDB - activeUserCountMapiHttpEmsMDB *prometheus.Desc + activeUserCountMapiHTTPEmsMDB *prometheus.Desc } -type perfDataCounterValuesMapiHttpEmsmdb struct { +type perfDataCounterValuesMapiHTTPEmsMDB struct { ActiveUserCount float64 `perfdata:"Active User Count"` } -func (c *Collector) buildMapiHttpEmsmdb() error { +func (c *Collector) buildMapiHTTPEmsMDB() error { var err error - c.perfDataCollectorMapiHttpEmsmdb, err = pdh.NewCollector[perfDataCounterValuesMapiHttpEmsmdb](pdh.CounterTypeRaw, "MSExchange MapiHttp Emsmdb", pdh.InstancesAll) + c.perfDataCollectorMapiHTTPEmsMDB, err = pdh.NewCollector[perfDataCounterValuesMapiHTTPEmsMDB](pdh.CounterTypeRaw, "MSExchange MapiHttp Emsmdb", pdh.InstancesAll) if err != nil { return fmt.Errorf("failed to create MSExchange MapiHttp Emsmdb: %w", err) } - c.activeUserCountMapiHttpEmsMDB = prometheus.NewDesc( + c.activeUserCountMapiHTTPEmsMDB = prometheus.NewDesc( prometheus.BuildFQName(types.Namespace, Name, "mapihttp_emsmdb_active_user_count"), "Number of unique outlook users that have shown some kind of activity in the last 2 minutes", nil, @@ -52,15 +52,15 @@ func (c *Collector) buildMapiHttpEmsmdb() error { return nil } -func (c *Collector) collectMapiHttpEmsmdb(ch chan<- prometheus.Metric) error { - err := c.perfDataCollectorMapiHttpEmsmdb.Collect(&c.perfDataObjectMapiHttpEmsmdb) +func (c *Collector) collectMapiHTTPEmsMDB(ch chan<- prometheus.Metric) error { + err := c.perfDataCollectorMapiHTTPEmsMDB.Collect(&c.perfDataObjectMapiHTTPEmsMDB) if err != nil { return fmt.Errorf("failed to collect MSExchange MapiHttp Emsmdb metrics: %w", err) } - for _, data := range c.perfDataObjectMapiHttpEmsmdb { + for _, data := range c.perfDataObjectMapiHTTPEmsMDB { ch <- prometheus.MustNewConstMetric( - c.activeUserCountMapiHttpEmsMDB, + c.activeUserCountMapiHTTPEmsMDB, prometheus.GaugeValue, data.ActiveUserCount, ) diff --git a/internal/httphandler/httphandler.go b/internal/httphandler/httphandler.go index 0dc830ec..36ab0d76 100644 --- a/internal/httphandler/httphandler.go +++ b/internal/httphandler/httphandler.go @@ -93,7 +93,7 @@ func (c *MetricsHTTPHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { ) w.WriteHeader(http.StatusBadRequest) - _, _ = w.Write([]byte(fmt.Sprintf("Couldn't create filtered metrics handler: %s", err))) + _, _ = fmt.Fprintf(w, "Couldn't create filtered metrics handler: %s", err) return } diff --git a/internal/log/logger.go b/internal/log/logger.go index 23006aae..d197dcaa 100644 --- a/internal/log/logger.go +++ b/internal/log/logger.go @@ -81,8 +81,8 @@ func New(config *Config) (*slog.Logger, error) { return nil, errors.New("log file undefined") } - config.Config.Writer = config.File.w - config.Config.Style = promslog.SlogStyle + config.Writer = config.File.w + config.Style = promslog.SlogStyle return promslog.New(config.Config), nil } diff --git a/internal/mi/application.go b/internal/mi/application.go index e66e39d9..9f73b9b9 100644 --- a/internal/mi/application.go +++ b/internal/mi/application.go @@ -26,13 +26,12 @@ import ( ) const ( - applicationID = "windows_exporter" - LocaleEnglish = "en-us" ) //nolint:gochecknoglobals var ( + applicationID = UTF16PtrFromString[*uint16]("windows_exporter") // DestinationOptionsTimeout is the key for the timeout option. // // https://github.com/microsoft/win32metadata/blob/527806d20d83d3abd43d16cd3fa8795d8deba343/generation/WinSDK/RecompiledIdlHeaders/um/mi.h#L7830 @@ -99,21 +98,16 @@ type DestinationOptionsFT struct { GetInterval uintptr } -// Application_Initialize initializes the MI [Application]. +// ApplicationInitialize initializes the MI [Application]. // It is recommended to have only one Application per process. // // https://learn.microsoft.com/en-us/windows/win32/api/mi/nf-mi-mi_application_initializev1 -func Application_Initialize() (*Application, error) { +func ApplicationInitialize() (*Application, error) { application := &Application{} - applicationId, err := windows.UTF16PtrFromString(applicationID) - if err != nil { - return nil, err - } - r0, _, err := procMIApplicationInitialize.Call( 0, - uintptr(unsafe.Pointer(applicationId)), + uintptr(unsafe.Pointer(applicationID)), 0, uintptr(unsafe.Pointer(application)), ) @@ -129,7 +123,7 @@ func Application_Initialize() (*Application, error) { return application, nil } -// Close deinitializes the management infrastructure client API that was initialized through a call to Application_Initialize. +// Close deinitializes the management infrastructure client API that was initialized through a call to ApplicationInitialize. // // https://learn.microsoft.com/en-us/windows/win32/api/mi/nf-mi-mi_application_close func (application *Application) Close() error { diff --git a/internal/mi/instance.go b/internal/mi/instance.go index 7f97b6c4..f0b007a0 100644 --- a/internal/mi/instance.go +++ b/internal/mi/instance.go @@ -164,29 +164,3 @@ func (instance *Instance) GetClassName() (string, error) { return windows.UTF16PtrToString(classNameUTF16), nil } - -func Instance_Print(instance *Instance) (string, error) { - elementMap := map[string]any{} - - properties := instance.classDecl.Properties() - - count, err := instance.GetElementCount() - if err != nil { - return "", err - } - - if count == 0 { - return "", nil - } - - for _, property := range properties { - name := windows.UTF16PtrToString(property.Name) - - element, _ := instance.GetElement(name) - value, _ := element.GetValue() - - elementMap[windows.UTF16PtrToString(property.Name)] = value - } - - return fmt.Sprintf("%v", elementMap), nil -} diff --git a/internal/mi/mi_bench_test.go b/internal/mi/mi_bench_test.go index 0161b98f..6b250bd8 100644 --- a/internal/mi/mi_bench_test.go +++ b/internal/mi/mi_bench_test.go @@ -23,7 +23,7 @@ import ( ) func Benchmark_MI_Query_Unmarshal(b *testing.B) { - application, err := mi.Application_Initialize() + application, err := mi.ApplicationInitialize() require.NoError(b, err) require.NotEmpty(b, application) diff --git a/internal/mi/mi_test.go b/internal/mi/mi_test.go index af3cf51c..e2baa0c2 100644 --- a/internal/mi/mi_test.go +++ b/internal/mi/mi_test.go @@ -28,7 +28,7 @@ type win32Process struct { } func Test_MI_Application_Initialize(t *testing.T) { - application, err := mi.Application_Initialize() + application, err := mi.ApplicationInitialize() require.NoError(t, err) require.NotEmpty(t, application) @@ -37,7 +37,7 @@ func Test_MI_Application_Initialize(t *testing.T) { } func Test_MI_Application_TestConnection(t *testing.T) { - application, err := mi.Application_Initialize() + application, err := mi.ApplicationInitialize() require.NoError(t, err) require.NotEmpty(t, application) @@ -67,7 +67,7 @@ func Test_MI_Application_TestConnection(t *testing.T) { } func Test_MI_Query(t *testing.T) { - application, err := mi.Application_Initialize() + application, err := mi.ApplicationInitialize() require.NoError(t, err) require.NotEmpty(t, application) @@ -120,7 +120,7 @@ func Test_MI_Query(t *testing.T) { } func Test_MI_QueryUnmarshal(t *testing.T) { - application, err := mi.Application_Initialize() + application, err := mi.ApplicationInitialize() require.NoError(t, err) require.NotEmpty(t, application) @@ -155,7 +155,7 @@ func Test_MI_QueryUnmarshal(t *testing.T) { } func Test_MI_EmptyQuery(t *testing.T) { - application, err := mi.Application_Initialize() + application, err := mi.ApplicationInitialize() require.NoError(t, err) require.NotEmpty(t, application) @@ -194,7 +194,7 @@ func Test_MI_EmptyQuery(t *testing.T) { } func Test_MI_Query_Unmarshal(t *testing.T) { - application, err := mi.Application_Initialize() + application, err := mi.ApplicationInitialize() require.NoError(t, err) require.NotEmpty(t, application) diff --git a/internal/utils/testutils/testutils.go b/internal/utils/testutils/testutils.go index bbaac6be..4bab58c0 100644 --- a/internal/utils/testutils/testutils.go +++ b/internal/utils/testutils/testutils.go @@ -74,7 +74,7 @@ func TestCollector[C collector.Collector, V interface{}](t *testing.T, fn func(* c := fn(conf) ch := make(chan prometheus.Metric, 10000) - miApp, err := mi.Application_Initialize() + miApp, err := mi.ApplicationInitialize() require.NoError(t, err) miSession, err := miApp.NewSession(nil) diff --git a/pkg/collector/collection.go b/pkg/collector/collection.go index 4919c3eb..58a44d56 100644 --- a/pkg/collector/collection.go +++ b/pkg/collector/collection.go @@ -275,7 +275,7 @@ func (c *Collection) Close() error { // initMI To be called by the exporter for collector initialization. func (c *Collection) initMI() error { - app, err := mi.Application_Initialize() + app, err := mi.ApplicationInitialize() if err != nil { return fmt.Errorf("error from initialize MI application: %w", err) }