mirror of
https://github.com/prometheus-community/windows_exporter.git
synced 2026-02-09 14:36:38 +00:00
Compare commits
5 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d31ce0507c | ||
|
|
faa98d2708 | ||
|
|
f0f3d0d96e | ||
|
|
f73a74b678 | ||
|
|
b6f89ad92f |
38
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
38
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
@@ -0,0 +1,38 @@
|
||||
<!--
|
||||
Please give your PR a title in the form "area: short description". For example "cpu: reduce usage by 95%" or "docs: fix typo in installation.md".
|
||||
|
||||
If your PR is to fix an issue, put "Fixes #issue-number" in the description.
|
||||
|
||||
Don't forget!
|
||||
|
||||
- Please sign CNCF's Developer Certificate of Origin and sign-off your commits by adding the -s / --signoff flag to `git commit`. See https://github.com/apps/dco for more information.
|
||||
|
||||
- If the PR adds or changes a behaviour or fixes a bug of an exported API it would need a unit/e2e test.
|
||||
|
||||
- Performance improvements would need a benchmark test to prove it.
|
||||
|
||||
- All comments should start with a capital letter and end with a full stop.
|
||||
-->
|
||||
|
||||
|
||||
#### What this PR does / why we need it
|
||||
|
||||
#### Which issue this PR fixes
|
||||
|
||||
*(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close that issue when PR gets merged)*: fixes #
|
||||
|
||||
- fixes #
|
||||
|
||||
#### Special notes for your reviewer
|
||||
|
||||
#### Particularly user-facing changes
|
||||
|
||||
#### Checklist
|
||||
|
||||
Complete these before marking the PR as `ready to review`:
|
||||
|
||||
<!-- [Place an '[x]' (no spaces) in all applicable fields.] -->
|
||||
|
||||
- [ ] [DCO](https://github.com/prometheus-community/helm-charts/blob/main/CONTRIBUTING.md#sign-off-your-work) signed
|
||||
- [ ] The PR title has a summary of the changes and the area they affect
|
||||
- [ ] The PR body has a summary to reflect any significant (and particularly user-facing) changes introduced by this PR
|
||||
82
CONTRIBUTING.md
Normal file
82
CONTRIBUTING.md
Normal file
@@ -0,0 +1,82 @@
|
||||
# Contributing
|
||||
|
||||
windows_exporter uses GitHub to manage reviews of pull requests.
|
||||
|
||||
* If you are a new contributor see: [Steps to Contribute](#steps-to-contribute)
|
||||
|
||||
* If you have a trivial fix or improvement, go ahead and create a pull request,
|
||||
addressing (with `@...`) a suitable maintainer of this repository (see
|
||||
[MAINTAINERS.md](MAINTAINERS.md)) in the description of the pull request.
|
||||
|
||||
* If you plan to do something more involved, first discuss your ideas
|
||||
as [github issue](https://github.com/prometheus-community/windows_exporter/issues).
|
||||
This will avoid unnecessary work and surely give you and us a good deal
|
||||
of inspiration. New collectors are unlikely to be accepted, since the
|
||||
`performancecounter` collector is the preferred way to collect metrics.
|
||||
|
||||
* Relevant coding style guidelines are the [Go Code Review
|
||||
Comments](https://code.google.com/p/go-wiki/wiki/CodeReviewComments)
|
||||
and the _Formatting and style_ section of Peter Bourgon's [Go: Best
|
||||
Practices for Production
|
||||
Environments](https://peter.bourgon.org/go-in-production/#formatting-and-style).
|
||||
gofmt and [golangci-lint](https://github.com/golangci/golangci-lint) are your friends.
|
||||
|
||||
* Be sure to sign off on the [DCO](https://github.com/probot/dco#how-it-works).
|
||||
|
||||
## Steps to Contribute
|
||||
|
||||
Should you wish to work on an issue, please claim it first by commenting on the GitHub issue that you want to work on it. This is to prevent duplicated efforts from contributors on the same issue.
|
||||
For quickly compiling and testing your changes do:
|
||||
|
||||
```bash
|
||||
# For building.
|
||||
go build -o windows_exporter.exe ./cmd/windows_exporter/
|
||||
./windows_exporter.exe
|
||||
|
||||
# For testing.
|
||||
make test # Make sure all the tests pass before you commit and push :)
|
||||
```
|
||||
|
||||
To run a collection of Go linters through [`golangci-lint`](https://github.com/golangci/golangci-lint), do:
|
||||
```bash
|
||||
make lint
|
||||
```
|
||||
|
||||
If it reports an issue and you think that the warning needs to be disregarded or is a false-positive, you can add a special comment `//nolint:linter1[,linter2,...]` before the offending line. Use this sparingly though, fixing the code to comply with the linter's recommendation is in general the preferred course of action. See [this section of the golangci-lint documentation](https://golangci-lint.run/usage/false-positives/#nolint-directive) for more information.
|
||||
|
||||
All our issues are regularly tagged so that you can also filter down the issues involving the components you want to work on. For our labeling policy refer [the wiki page](https://github.com/prometheus/prometheus/wiki/Label-Names-and-Descriptions).
|
||||
|
||||
## Pull Request Checklist
|
||||
|
||||
* Branch from the main branch and, if needed, rebase to the current main branch before submitting your pull request. If it doesn't merge cleanly with main you may be asked to rebase your changes.
|
||||
|
||||
* Commits should be as small as possible, while ensuring that each commit is correct independently (i.e., each commit should compile and pass tests).
|
||||
|
||||
* The PR title should be of the format: `subsystem: what this PR does` (for example, `cpu: Add support for thing` or `docs: fix typo`).
|
||||
|
||||
* If your patch is not getting reviewed or you need a specific person to review it, you can @-reply a reviewer asking for a review in the pull request or a comment.
|
||||
|
||||
* Add tests relevant to the fixed bug or new feature.
|
||||
|
||||
## Dependency management
|
||||
|
||||
The Prometheus project uses [Go modules](https://golang.org/cmd/go/#hdr-Modules__module_versions__and_more) to manage dependencies on external packages.
|
||||
|
||||
To add or update a new dependency, use the `go get` command:
|
||||
|
||||
```bash
|
||||
# Pick the latest tagged release.
|
||||
go get example.com/some/module/pkg@latest
|
||||
|
||||
# Pick a specific version.
|
||||
go get example.com/some/module/pkg@vX.Y.Z
|
||||
```
|
||||
|
||||
Tidy up the `go.mod` and `go.sum` files:
|
||||
|
||||
```bash
|
||||
# The GO111MODULE variable can be omitted when the code isn't located in GOPATH.
|
||||
GO111MODULE=on go mod tidy
|
||||
```
|
||||
|
||||
You have to commit the changes to `go.mod` and `go.sum` before submitting the pull request.
|
||||
1
LICENSE
1
LICENSE
@@ -1,6 +1,7 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2016 Martin Lindhe
|
||||
Copyright (c) 2021 The Prometheus Authors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
147
cmd/windows_exporter/0_service.go
Normal file
147
cmd/windows_exporter/0_service.go
Normal file
@@ -0,0 +1,147 @@
|
||||
// Copyright 2025 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
"golang.org/x/sys/windows/svc"
|
||||
"golang.org/x/sys/windows/svc/eventlog"
|
||||
)
|
||||
|
||||
const serviceName = "windows_exporter"
|
||||
|
||||
//nolint:gochecknoglobals
|
||||
var (
|
||||
// exitCodeCh is a channel to send an exit code from the main function to the service manager.
|
||||
// Additionally, if there is an error in the IsService var declaration,
|
||||
// the exit code is sent to the service manager as well.
|
||||
exitCodeCh = make(chan int, 1)
|
||||
|
||||
// stopCh is a channel to send a signal to the service manager that the service is stopping.
|
||||
stopCh = make(chan struct{})
|
||||
)
|
||||
|
||||
// IsService variable declaration allows initiating time-sensitive components like registering the Windows service
|
||||
// as early as possible in the startup process.
|
||||
// init functions are called in the order they are declared, so this package should be imported first.
|
||||
//
|
||||
// Ref: https://github.com/prometheus-community/windows_exporter/issues/551#issuecomment-1220774835
|
||||
//
|
||||
// Declare imports on this package should be avoided where possible.
|
||||
// var declaration run before init function, so it guarantees that windows_exporter respond to service manager early
|
||||
// and avoid timeout.
|
||||
// The order of the var declaration and init functions depends on the filename as well. The filename should be 0_service.go
|
||||
// Ref: https://medium.com/@markbates/go-init-order-dafa89fcef22
|
||||
//
|
||||
//nolint:gochecknoglobals
|
||||
var IsService = func() bool {
|
||||
defer func() {
|
||||
go func() {
|
||||
err := svc.Run(serviceName, &windowsExporterService{})
|
||||
if err == nil {
|
||||
return
|
||||
}
|
||||
|
||||
_ = logToEventToLog(windows.EVENTLOG_ERROR_TYPE, fmt.Sprintf("failed to start service: %v", err))
|
||||
}()
|
||||
}()
|
||||
|
||||
var err error
|
||||
|
||||
isService, err := svc.IsWindowsService()
|
||||
if err != nil {
|
||||
_ = logToEventToLog(windows.EVENTLOG_ERROR_TYPE, fmt.Sprintf("failed to detect service: %v", err))
|
||||
|
||||
exitCodeCh <- 1
|
||||
}
|
||||
|
||||
if !isService {
|
||||
return false
|
||||
}
|
||||
|
||||
if err := logToEventToLog(windows.EVENTLOG_INFORMATION_TYPE, "attempting to start exporter service"); err != nil {
|
||||
//nolint:gosec
|
||||
_ = os.WriteFile("C:\\Program Files\\windows_exporter\\start-service.error.log", []byte(fmt.Sprintf("failed sent log to event log: %v", err)), 0o644)
|
||||
|
||||
exitCodeCh <- 2
|
||||
}
|
||||
|
||||
return true
|
||||
}()
|
||||
|
||||
type windowsExporterService struct{}
|
||||
|
||||
// Execute is the entry point for the Windows service manager.
|
||||
func (s *windowsExporterService) Execute(_ []string, r <-chan svc.ChangeRequest, changes chan<- svc.Status) (bool, uint32) {
|
||||
changes <- svc.Status{State: svc.StartPending}
|
||||
changes <- svc.Status{State: svc.Running, Accepts: svc.AcceptStop | svc.AcceptShutdown}
|
||||
|
||||
for {
|
||||
select {
|
||||
case exitCodeCh := <-exitCodeCh:
|
||||
// Stop the service if an exit code from the main function is received.
|
||||
changes <- svc.Status{State: svc.StopPending}
|
||||
|
||||
return true, uint32(exitCodeCh)
|
||||
case c := <-r:
|
||||
// Handle the service control request.
|
||||
switch c.Cmd {
|
||||
case svc.Interrogate:
|
||||
changes <- c.CurrentStatus
|
||||
case svc.Stop, svc.Shutdown:
|
||||
// Stop the service if a stop or shutdown request is received.
|
||||
_ = logToEventToLog(windows.EVENTLOG_INFORMATION_TYPE, "service stop received")
|
||||
|
||||
changes <- svc.Status{State: svc.StopPending}
|
||||
|
||||
// Send a signal to the main function to stop the service.
|
||||
stopCh <- struct{}{}
|
||||
|
||||
// Wait for the main function to stop the service.
|
||||
return false, uint32(<-exitCodeCh)
|
||||
default:
|
||||
_ = logToEventToLog(windows.EVENTLOG_ERROR_TYPE, fmt.Sprintf("unexpected control request #%d", c))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// logToEventToLog logs a message to the Windows event log.
|
||||
func logToEventToLog(eType uint16, msg string) error {
|
||||
eventLog, err := eventlog.Open("windows_exporter")
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to open event log: %w", err)
|
||||
}
|
||||
defer func(eventLog *eventlog.Log) {
|
||||
_ = eventLog.Close()
|
||||
}(eventLog)
|
||||
|
||||
p, err := windows.UTF16PtrFromString(msg)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error convert string to UTF-16: %w", err)
|
||||
}
|
||||
|
||||
zero := uint16(0)
|
||||
ss := []*uint16{p, &zero, &zero, &zero, &zero, &zero, &zero, &zero, &zero}
|
||||
|
||||
err = windows.ReportEvent(eventLog.Handle, eType, 0, 3299, 0, 9, 0, &ss[0], nil)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error report event: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -17,12 +17,7 @@
|
||||
|
||||
package main
|
||||
|
||||
//goland:noinspection GoUnsortedImport
|
||||
//nolint:gofumpt
|
||||
import (
|
||||
// Its important that we do these first so that we can register with the Windows service control ASAP to avoid timeouts.
|
||||
"github.com/prometheus-community/windows_exporter/internal/windowsservice"
|
||||
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
@@ -55,14 +50,14 @@ func main() {
|
||||
exitCode := run()
|
||||
|
||||
// If we are running as a service, we need to signal the service control manager that we are done.
|
||||
if !windowsservice.IsService {
|
||||
if !IsService {
|
||||
os.Exit(exitCode)
|
||||
}
|
||||
|
||||
windowsservice.ExitCodeCh <- exitCode
|
||||
exitCodeCh <- exitCode
|
||||
|
||||
// Wait for the service control manager to signal that we are done.
|
||||
<-windowsservice.StopCh
|
||||
<-stopCh
|
||||
}
|
||||
|
||||
func run() int {
|
||||
@@ -114,7 +109,7 @@ func run() int {
|
||||
logFile := &log.AllowedFile{}
|
||||
|
||||
_ = logFile.Set("stdout")
|
||||
if windowsservice.IsService {
|
||||
if IsService {
|
||||
_ = logFile.Set("eventlog")
|
||||
}
|
||||
|
||||
@@ -276,7 +271,7 @@ func run() int {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
logger.Info("Shutting down windows_exporter via kill signal")
|
||||
case <-windowsservice.StopCh:
|
||||
case <-stopCh:
|
||||
logger.Info("Shutting down windows_exporter via service control")
|
||||
case err := <-errCh:
|
||||
if err != nil {
|
||||
|
||||
@@ -27,10 +27,15 @@
|
||||
ErrorControl="normal"
|
||||
Start="auto"
|
||||
Type="ownProcess"
|
||||
Interactive="no"
|
||||
Vital="yes"
|
||||
Arguments="[ConfigFileFlag] [CollectorsFlag] [ListenFlag] [MetricsPathFlag] [TextfileDirsFlag] [ExtraFlags]">
|
||||
<ServiceConfig
|
||||
DelayedAutoStart="yes"
|
||||
OnInstall="yes"
|
||||
OnReinstall="yes" />
|
||||
<util:ServiceConfig
|
||||
ResetPeriodInDays="1"
|
||||
ResetPeriodInDays="0"
|
||||
FirstFailureActionType="restart"
|
||||
SecondFailureActionType="restart"
|
||||
ThirdFailureActionType="restart"
|
||||
|
||||
@@ -391,7 +391,7 @@ func (c *Collector) collectNICAddresses(ch chan<- prometheus.Metric) error {
|
||||
return err
|
||||
}
|
||||
|
||||
convertNicName := strings.NewReplacer("(", "[", ")", "]")
|
||||
convertNicName := strings.NewReplacer("(", "[", ")", "]", "#", "_")
|
||||
|
||||
for _, nicAdapterAddress := range nicAdapterAddresses {
|
||||
friendlyName := windows.UTF16PtrToString(nicAdapterAddress.FriendlyName)
|
||||
|
||||
@@ -20,6 +20,7 @@ import (
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/alecthomas/kingpin/v2"
|
||||
@@ -143,8 +144,26 @@ func New(config *Config) *Collector {
|
||||
return c
|
||||
}
|
||||
|
||||
func NewWithFlags(_ *kingpin.Application) *Collector {
|
||||
return &Collector{}
|
||||
func NewWithFlags(app *kingpin.Application) *Collector {
|
||||
c := &Collector{
|
||||
config: ConfigDefaults,
|
||||
}
|
||||
c.config.CollectorsEnabled = make([]string, 0)
|
||||
|
||||
var collectorsEnabled string
|
||||
|
||||
app.Flag(
|
||||
"collector.netframework.enabled",
|
||||
"Comma-separated list of collectors to use. Defaults to all, if not specified.",
|
||||
).Default(strings.Join(ConfigDefaults.CollectorsEnabled, ",")).StringVar(&collectorsEnabled)
|
||||
|
||||
app.Action(func(*kingpin.ParseContext) error {
|
||||
c.config.CollectorsEnabled = strings.Split(collectorsEnabled, ",")
|
||||
|
||||
return nil
|
||||
})
|
||||
|
||||
return c
|
||||
}
|
||||
|
||||
func (c *Collector) GetName() string {
|
||||
|
||||
@@ -34,6 +34,9 @@ const (
|
||||
// Interface guard.
|
||||
var _ io.Writer = (*Writer)(nil)
|
||||
|
||||
//nolint:gochecknoglobals
|
||||
var EmptyStringUTF16 uint16
|
||||
|
||||
type Writer struct {
|
||||
handle windows.Handle
|
||||
}
|
||||
@@ -60,7 +63,7 @@ func (w *Writer) Write(p []byte) (int, error) {
|
||||
return 0, fmt.Errorf("error convert string to UTF-16: %w", err)
|
||||
}
|
||||
|
||||
ss := []*uint16{msg, nil, nil, nil, nil, nil, nil, nil, nil}
|
||||
ss := []*uint16{msg, &EmptyStringUTF16, &EmptyStringUTF16, &EmptyStringUTF16, &EmptyStringUTF16, &EmptyStringUTF16, &EmptyStringUTF16, &EmptyStringUTF16, &EmptyStringUTF16}
|
||||
|
||||
return len(p), windows.ReportEvent(w.handle, eType, 0, NeLogOemCode, 0, 9, 0, &ss[0], nil)
|
||||
}
|
||||
|
||||
@@ -1,23 +0,0 @@
|
||||
// Copyright 2024 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//go:build windows
|
||||
|
||||
// Package windowsservice allows initiating time-sensitive components like registering the Windows service
|
||||
// as early as possible in the startup process.
|
||||
// init functions are called in the order they are declared, so this package should be imported first.
|
||||
// Declare imports on this package should be avoided where possible.
|
||||
//
|
||||
// Ref: https://github.com/prometheus-community/windows_exporter/issues/551#issuecomment-1220774835
|
||||
|
||||
package windowsservice
|
||||
@@ -1,61 +0,0 @@
|
||||
// Copyright 2024 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package windowsservice
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
"golang.org/x/sys/windows/svc"
|
||||
)
|
||||
|
||||
//nolint:gochecknoglobals
|
||||
var (
|
||||
// IsService is true if the exporter is running as a Windows service.
|
||||
IsService bool
|
||||
// ExitCodeCh is a channel to send the exit code return from the [github.com/prometheus-community/windows_exporter/cmd/windows_exporter] function to the service manager.
|
||||
ExitCodeCh = make(chan int)
|
||||
|
||||
// StopCh is a channel to send a signal to the service manager that the service is stopping.
|
||||
StopCh = make(chan struct{})
|
||||
)
|
||||
|
||||
//nolint:gochecknoinits // An init function is required to communicate with the Windows service manager early in the program.
|
||||
func init() {
|
||||
var err error
|
||||
|
||||
IsService, err = svc.IsWindowsService()
|
||||
if err != nil {
|
||||
if err := logToEventToLog(windows.EVENTLOG_ERROR_TYPE, fmt.Sprintf("failed to detect service: %v", err)); err != nil {
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if !IsService {
|
||||
return
|
||||
}
|
||||
|
||||
if err := logToEventToLog(windows.EVENTLOG_INFORMATION_TYPE, "attempting to start exporter service"); err != nil {
|
||||
os.Exit(2)
|
||||
}
|
||||
|
||||
go func() {
|
||||
if err := svc.Run(serviceName, &windowsExporterService{}); err != nil {
|
||||
_ = logToEventToLog(windows.EVENTLOG_ERROR_TYPE, fmt.Sprintf("failed to start service: %v", err))
|
||||
}
|
||||
}()
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
// Copyright 2024 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//go:build windows
|
||||
|
||||
package windowsservice
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
wineventlog "github.com/prometheus-community/windows_exporter/internal/log/eventlog"
|
||||
"golang.org/x/sys/windows"
|
||||
"golang.org/x/sys/windows/svc/eventlog"
|
||||
)
|
||||
|
||||
// logToEventToLog logs a message to the Windows event log.
|
||||
func logToEventToLog(eType uint16, msg string) error {
|
||||
eventLog, err := eventlog.Open("windows_exporter")
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to open event log: %w", err)
|
||||
}
|
||||
defer func(eventLog *eventlog.Log) {
|
||||
_ = eventLog.Close()
|
||||
}(eventLog)
|
||||
|
||||
p, err := windows.UTF16PtrFromString(msg)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error convert string to UTF-16: %w", err)
|
||||
}
|
||||
|
||||
ss := []*uint16{p, nil, nil, nil, nil, nil, nil, nil, nil}
|
||||
|
||||
return windows.ReportEvent(eventLog.Handle, eType, 0, wineventlog.NeLogOemCode, 0, 9, 0, &ss[0], nil)
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
// Copyright 2024 The Prometheus Authors
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
//go:build windows
|
||||
|
||||
package windowsservice
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"golang.org/x/sys/windows"
|
||||
"golang.org/x/sys/windows/svc"
|
||||
)
|
||||
|
||||
const (
|
||||
serviceName = "windows_exporter"
|
||||
)
|
||||
|
||||
type windowsExporterService struct{}
|
||||
|
||||
// Execute is the entry point for the Windows service manager.
|
||||
func (s *windowsExporterService) Execute(_ []string, r <-chan svc.ChangeRequest, changes chan<- svc.Status) (bool, uint32) {
|
||||
changes <- svc.Status{State: svc.StartPending}
|
||||
changes <- svc.Status{State: svc.Running, Accepts: svc.AcceptStop | svc.AcceptShutdown}
|
||||
|
||||
for {
|
||||
select {
|
||||
case exitCodeCh := <-ExitCodeCh:
|
||||
// Stop the service if an exit code from the main function is received.
|
||||
changes <- svc.Status{State: svc.StopPending}
|
||||
|
||||
return true, uint32(exitCodeCh)
|
||||
case c := <-r:
|
||||
// Handle the service control request.
|
||||
switch c.Cmd {
|
||||
case svc.Interrogate:
|
||||
changes <- c.CurrentStatus
|
||||
case svc.Stop, svc.Shutdown:
|
||||
// Stop the service if a stop or shutdown request is received.
|
||||
_ = logToEventToLog(windows.EVENTLOG_INFORMATION_TYPE, "service stop received")
|
||||
|
||||
changes <- svc.Status{State: svc.StopPending}
|
||||
|
||||
// Send a signal to the main function to stop the service.
|
||||
StopCh <- struct{}{}
|
||||
|
||||
// Wait for the main function to stop the service.
|
||||
return false, uint32(<-ExitCodeCh)
|
||||
default:
|
||||
_ = logToEventToLog(windows.EVENTLOG_ERROR_TYPE, fmt.Sprintf("unexpected control request #%d", c))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user