TUN-8792: Make diag/system endpoint always return a JSON
## Summary Change the system information collector and respective http handler so that it always returns a JSON. Closes [TUN-8792](https://jira.cfdata.org/browse/TUN-8792)
This commit is contained in:
parent
ba9f28ef43
commit
02e7ffd5b7
|
@ -141,7 +141,7 @@ func (client *httpClient) GetSystemInformation(ctx context.Context, writer io.Wr
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
return copyToWriter(response, writer)
|
return copyJSONToWriter(response, writer)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (client *httpClient) GetMetrics(ctx context.Context, writer io.Writer) error {
|
func (client *httpClient) GetMetrics(ctx context.Context, writer io.Writer) error {
|
||||||
|
|
|
@ -59,6 +59,11 @@ func (handler *Handler) InstallEndpoints(router *http.ServeMux) {
|
||||||
router.HandleFunc(systemInformationEndpoint, handler.SystemHandler)
|
router.HandleFunc(systemInformationEndpoint, handler.SystemHandler)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type SystemInformationResponse struct {
|
||||||
|
Info *SystemInformation `json:"info"`
|
||||||
|
Err error `json:"errors"`
|
||||||
|
}
|
||||||
|
|
||||||
func (handler *Handler) SystemHandler(writer http.ResponseWriter, request *http.Request) {
|
func (handler *Handler) SystemHandler(writer http.ResponseWriter, request *http.Request) {
|
||||||
logger := handler.log.With().Str(collectorField, systemCollectorName).Logger()
|
logger := handler.log.With().Str(collectorField, systemCollectorName).Logger()
|
||||||
logger.Info().Msg("Collection started")
|
logger.Info().Msg("Collection started")
|
||||||
|
@ -69,30 +74,15 @@ func (handler *Handler) SystemHandler(writer http.ResponseWriter, request *http.
|
||||||
|
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
info, rawInfo, err := handler.systemCollector.Collect(ctx)
|
info, err := handler.systemCollector.Collect(ctx)
|
||||||
if err != nil {
|
|
||||||
logger.Error().Err(err).Msg("error occurred whilst collecting system information")
|
|
||||||
|
|
||||||
if rawInfo != "" {
|
response := SystemInformationResponse{
|
||||||
logger.Info().Msg("using raw information fallback")
|
Info: info,
|
||||||
bytes := []byte(rawInfo)
|
Err: err,
|
||||||
writeResponse(writer, bytes, &logger)
|
|
||||||
} else {
|
|
||||||
logger.Error().Msg("no raw information available")
|
|
||||||
writer.WriteHeader(http.StatusInternalServerError)
|
|
||||||
}
|
|
||||||
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if info == nil {
|
|
||||||
logger.Error().Msgf("system information collection is nil")
|
|
||||||
writer.WriteHeader(http.StatusInternalServerError)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
encoder := json.NewEncoder(writer)
|
encoder := json.NewEncoder(writer)
|
||||||
|
err = encoder.Encode(response)
|
||||||
err = encoder.Encode(info)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error().Err(err).Msgf("error occurred whilst serializing information")
|
logger.Error().Err(err).Msgf("error occurred whilst serializing information")
|
||||||
writer.WriteHeader(http.StatusInternalServerError)
|
writer.WriteHeader(http.StatusInternalServerError)
|
||||||
|
|
|
@ -4,10 +4,10 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"io"
|
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
|
"runtime"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
|
@ -20,11 +20,13 @@ import (
|
||||||
"github.com/cloudflare/cloudflared/tunnelstate"
|
"github.com/cloudflare/cloudflared/tunnelstate"
|
||||||
)
|
)
|
||||||
|
|
||||||
type SystemCollectorMock struct{}
|
type SystemCollectorMock struct {
|
||||||
|
systemInfo *diagnostic.SystemInformation
|
||||||
|
err error
|
||||||
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
systemInformationKey = "sikey"
|
systemInformationKey = "sikey"
|
||||||
rawInformationKey = "rikey"
|
|
||||||
errorKey = "errkey"
|
errorKey = "errkey"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -46,24 +48,8 @@ func newTrackerFromConns(t *testing.T, connections []tunnelstate.IndexedConnecti
|
||||||
return tracker
|
return tracker
|
||||||
}
|
}
|
||||||
|
|
||||||
func setCtxValuesForSystemCollector(
|
func (collector *SystemCollectorMock) Collect(context.Context) (*diagnostic.SystemInformation, error) {
|
||||||
systemInfo *diagnostic.SystemInformation,
|
return collector.systemInfo, collector.err
|
||||||
rawInfo string,
|
|
||||||
err error,
|
|
||||||
) context.Context {
|
|
||||||
ctx := context.Background()
|
|
||||||
ctx = context.WithValue(ctx, systemInformationKey, systemInfo)
|
|
||||||
ctx = context.WithValue(ctx, rawInformationKey, rawInfo)
|
|
||||||
ctx = context.WithValue(ctx, errorKey, err)
|
|
||||||
|
|
||||||
return ctx
|
|
||||||
}
|
|
||||||
|
|
||||||
func (*SystemCollectorMock) Collect(ctx context.Context) (*diagnostic.SystemInformation, string, error) {
|
|
||||||
si, _ := ctx.Value(systemInformationKey).(*diagnostic.SystemInformation)
|
|
||||||
ri, _ := ctx.Value(rawInformationKey).(string)
|
|
||||||
err, _ := ctx.Value(errorKey).(error)
|
|
||||||
return si, ri, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSystemHandler(t *testing.T) {
|
func TestSystemHandler(t *testing.T) {
|
||||||
|
@ -73,7 +59,6 @@ func TestSystemHandler(t *testing.T) {
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
name string
|
name string
|
||||||
systemInfo *diagnostic.SystemInformation
|
systemInfo *diagnostic.SystemInformation
|
||||||
rawInfo string
|
|
||||||
err error
|
err error
|
||||||
statusCode int
|
statusCode int
|
||||||
}{
|
}{
|
||||||
|
@ -82,47 +67,39 @@ func TestSystemHandler(t *testing.T) {
|
||||||
systemInfo: diagnostic.NewSystemInformation(
|
systemInfo: diagnostic.NewSystemInformation(
|
||||||
0, 0, 0, 0,
|
0, 0, 0, 0,
|
||||||
"string", "string", "string", "string",
|
"string", "string", "string", "string",
|
||||||
"string", "string", nil,
|
"string", "string",
|
||||||
|
runtime.Version(), runtime.GOARCH, nil,
|
||||||
),
|
),
|
||||||
rawInfo: "",
|
|
||||||
err: nil,
|
err: nil,
|
||||||
statusCode: http.StatusOK,
|
statusCode: http.StatusOK,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
name: "on error and raw info", systemInfo: nil,
|
|
||||||
rawInfo: "raw info", err: errors.New("an error"), statusCode: http.StatusOK,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: "on error and no raw info", systemInfo: nil,
|
name: "on error and no raw info", systemInfo: nil,
|
||||||
rawInfo: "", err: errors.New("an error"), statusCode: http.StatusInternalServerError,
|
err: errors.New("an error"), statusCode: http.StatusOK,
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "malformed response", systemInfo: nil, rawInfo: "", err: nil, statusCode: http.StatusInternalServerError,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tCase := range tests {
|
for _, tCase := range tests {
|
||||||
t.Run(tCase.name, func(t *testing.T) {
|
t.Run(tCase.name, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
handler := diagnostic.NewDiagnosticHandler(&log, 0, &SystemCollectorMock{}, uuid.New(), uuid.New(), nil, map[string]string{}, nil)
|
handler := diagnostic.NewDiagnosticHandler(&log, 0, &SystemCollectorMock{
|
||||||
|
systemInfo: tCase.systemInfo,
|
||||||
|
err: tCase.err,
|
||||||
|
}, uuid.New(), uuid.New(), nil, map[string]string{}, nil)
|
||||||
recorder := httptest.NewRecorder()
|
recorder := httptest.NewRecorder()
|
||||||
ctx := setCtxValuesForSystemCollector(tCase.systemInfo, tCase.rawInfo, tCase.err)
|
ctx := context.Background()
|
||||||
request, err := http.NewRequestWithContext(ctx, http.MethodGet, "/diag/syste,", nil)
|
request, err := http.NewRequestWithContext(ctx, http.MethodGet, "/diag/system", nil)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
handler.SystemHandler(recorder, request)
|
handler.SystemHandler(recorder, request)
|
||||||
|
|
||||||
assert.Equal(t, tCase.statusCode, recorder.Code)
|
assert.Equal(t, tCase.statusCode, recorder.Code)
|
||||||
if tCase.statusCode == http.StatusOK && tCase.systemInfo != nil {
|
if tCase.statusCode == http.StatusOK && tCase.systemInfo != nil {
|
||||||
var response diagnostic.SystemInformation
|
var response diagnostic.SystemInformationResponse
|
||||||
|
|
||||||
decoder := json.NewDecoder(recorder.Body)
|
decoder := json.NewDecoder(recorder.Body)
|
||||||
err = decoder.Decode(&response)
|
err := decoder.Decode(&response)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, tCase.systemInfo, &response)
|
assert.Equal(t, tCase.systemInfo, response.Info)
|
||||||
} else if tCase.statusCode == http.StatusOK && tCase.rawInfo != "" {
|
|
||||||
rawBytes, err := io.ReadAll(recorder.Body)
|
|
||||||
require.NoError(t, err)
|
|
||||||
assert.Equal(t, tCase.rawInfo, string(rawBytes))
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,82 @@
|
||||||
package diagnostic
|
package diagnostic
|
||||||
|
|
||||||
import "context"
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
type SystemInformationError struct {
|
||||||
|
Err error `json:"error"`
|
||||||
|
RawInfo string `json:"rawInfo"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (err SystemInformationError) Error() string {
|
||||||
|
return err.Err.Error()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (err SystemInformationError) MarshalJSON() ([]byte, error) {
|
||||||
|
s := map[string]string{
|
||||||
|
"error": err.Err.Error(),
|
||||||
|
"rawInfo": err.RawInfo,
|
||||||
|
}
|
||||||
|
|
||||||
|
return json.Marshal(s)
|
||||||
|
}
|
||||||
|
|
||||||
|
type SystemInformationGeneralError struct {
|
||||||
|
OperatingSystemInformationError error
|
||||||
|
MemoryInformationError error
|
||||||
|
FileDescriptorsInformationError error
|
||||||
|
DiskVolumeInformationError error
|
||||||
|
}
|
||||||
|
|
||||||
|
func (err SystemInformationGeneralError) Error() string {
|
||||||
|
builder := &strings.Builder{}
|
||||||
|
builder.WriteString("errors found:")
|
||||||
|
|
||||||
|
if err.OperatingSystemInformationError != nil {
|
||||||
|
builder.WriteString(err.OperatingSystemInformationError.Error() + ", ")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err.MemoryInformationError != nil {
|
||||||
|
builder.WriteString(err.MemoryInformationError.Error() + ", ")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err.FileDescriptorsInformationError != nil {
|
||||||
|
builder.WriteString(err.FileDescriptorsInformationError.Error() + ", ")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err.DiskVolumeInformationError != nil {
|
||||||
|
builder.WriteString(err.DiskVolumeInformationError.Error() + ", ")
|
||||||
|
}
|
||||||
|
|
||||||
|
return builder.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (err SystemInformationGeneralError) MarshalJSON() ([]byte, error) {
|
||||||
|
data := map[string]SystemInformationError{}
|
||||||
|
|
||||||
|
var sysErr SystemInformationError
|
||||||
|
if errors.As(err.OperatingSystemInformationError, &sysErr) {
|
||||||
|
data["operatingSystemInformationError"] = sysErr
|
||||||
|
}
|
||||||
|
|
||||||
|
if errors.As(err.MemoryInformationError, &sysErr) {
|
||||||
|
data["memoryInformationError"] = sysErr
|
||||||
|
}
|
||||||
|
|
||||||
|
if errors.As(err.FileDescriptorsInformationError, &sysErr) {
|
||||||
|
data["fileDescriptorsInformationError"] = sysErr
|
||||||
|
}
|
||||||
|
|
||||||
|
if errors.As(err.DiskVolumeInformationError, &sysErr) {
|
||||||
|
data["diskVolumeInformationError"] = sysErr
|
||||||
|
}
|
||||||
|
|
||||||
|
return json.Marshal(data)
|
||||||
|
}
|
||||||
|
|
||||||
type DiskVolumeInformation struct {
|
type DiskVolumeInformation struct {
|
||||||
Name string `json:"name"` // represents the filesystem in linux/macos or device name in windows
|
Name string `json:"name"` // represents the filesystem in linux/macos or device name in windows
|
||||||
|
@ -17,17 +93,19 @@ func NewDiskVolumeInformation(name string, maximum, current uint64) *DiskVolumeI
|
||||||
}
|
}
|
||||||
|
|
||||||
type SystemInformation struct {
|
type SystemInformation struct {
|
||||||
MemoryMaximum uint64 `json:"memoryMaximum"` // represents the maximum memory of the system in kilobytes
|
MemoryMaximum uint64 `json:"memoryMaximum,omitempty"` // represents the maximum memory of the system in kilobytes
|
||||||
MemoryCurrent uint64 `json:"memoryCurrent"` // represents the system's memory in use in kilobytes
|
MemoryCurrent uint64 `json:"memoryCurrent,omitempty"` // represents the system's memory in use in kilobytes
|
||||||
FileDescriptorMaximum uint64 `json:"fileDescriptorMaximum"` // represents the maximum number of file descriptors of the system
|
FileDescriptorMaximum uint64 `json:"fileDescriptorMaximum,omitempty"` // represents the maximum number of file descriptors of the system
|
||||||
FileDescriptorCurrent uint64 `json:"fileDescriptorCurrent"` // represents the system's file descriptors in use
|
FileDescriptorCurrent uint64 `json:"fileDescriptorCurrent,omitempty"` // represents the system's file descriptors in use
|
||||||
OsSystem string `json:"osSystem"` // represents the operating system name i.e.: linux, windows, darwin
|
OsSystem string `json:"osSystem,omitempty"` // represents the operating system name i.e.: linux, windows, darwin
|
||||||
HostName string `json:"hostName"` // represents the system host name
|
HostName string `json:"hostName,omitempty"` // represents the system host name
|
||||||
OsVersion string `json:"osVersion"` // detailed information about the system's release version level
|
OsVersion string `json:"osVersion,omitempty"` // detailed information about the system's release version level
|
||||||
OsRelease string `json:"osRelease"` // detailed information about the system's release
|
OsRelease string `json:"osRelease,omitempty"` // detailed information about the system's release
|
||||||
Architecture string `json:"architecture"` // represents the system's hardware platform i.e: arm64/amd64
|
Architecture string `json:"architecture,omitempty"` // represents the system's hardware platform i.e: arm64/amd64
|
||||||
CloudflaredVersion string `json:"cloudflaredVersion"` // the runtime version of cloudflared
|
CloudflaredVersion string `json:"cloudflaredVersion,omitempty"` // the runtime version of cloudflared
|
||||||
Disk []*DiskVolumeInformation `json:"disk"`
|
GoVersion string `json:"goVersion,omitempty"`
|
||||||
|
GoArch string `json:"goArch,omitempty"`
|
||||||
|
Disk []*DiskVolumeInformation `json:"disk,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewSystemInformation(
|
func NewSystemInformation(
|
||||||
|
@ -40,7 +118,9 @@ func NewSystemInformation(
|
||||||
osVersion,
|
osVersion,
|
||||||
osRelease,
|
osRelease,
|
||||||
architecture,
|
architecture,
|
||||||
cloudflaredVersion string,
|
cloudflaredVersion,
|
||||||
|
goVersion,
|
||||||
|
goArchitecture string,
|
||||||
disk []*DiskVolumeInformation,
|
disk []*DiskVolumeInformation,
|
||||||
) *SystemInformation {
|
) *SystemInformation {
|
||||||
return &SystemInformation{
|
return &SystemInformation{
|
||||||
|
@ -54,17 +134,17 @@ func NewSystemInformation(
|
||||||
osRelease,
|
osRelease,
|
||||||
architecture,
|
architecture,
|
||||||
cloudflaredVersion,
|
cloudflaredVersion,
|
||||||
|
goVersion,
|
||||||
|
goArchitecture,
|
||||||
disk,
|
disk,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type SystemCollector interface {
|
type SystemCollector interface {
|
||||||
// If the collection is successful it will return `SystemInformation` struct,
|
// If the collection is successful it will return `SystemInformation` struct,
|
||||||
// an empty string, and a nil error.
|
// and a nil error.
|
||||||
// In case there is an error a string with the raw data will be returned
|
|
||||||
// however the returned string not contain all the data points.
|
|
||||||
//
|
//
|
||||||
// This function expects that the caller sets the context timeout to prevent
|
// This function expects that the caller sets the context timeout to prevent
|
||||||
// long-lived collectors.
|
// long-lived collectors.
|
||||||
Collect(ctx context.Context) (*SystemInformation, string, error)
|
Collect(ctx context.Context) (*SystemInformation, error)
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
@ -22,45 +23,74 @@ func NewSystemCollectorImpl(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (collector *SystemCollectorImpl) Collect(ctx context.Context) (*SystemInformation, string, error) {
|
func (collector *SystemCollectorImpl) Collect(ctx context.Context) (*SystemInformation, error) {
|
||||||
memoryInfo, memoryInfoRaw, memoryInfoErr := collectMemoryInformation(ctx)
|
memoryInfo, memoryInfoRaw, memoryInfoErr := collectMemoryInformation(ctx)
|
||||||
fdInfo, fdInfoRaw, fdInfoErr := collectFileDescriptorInformation(ctx)
|
fdInfo, fdInfoRaw, fdInfoErr := collectFileDescriptorInformation(ctx)
|
||||||
disks, disksRaw, diskErr := collectDiskVolumeInformationUnix(ctx)
|
disks, disksRaw, diskErr := collectDiskVolumeInformationUnix(ctx)
|
||||||
osInfo, osInfoRaw, osInfoErr := collectOSInformationUnix(ctx)
|
osInfo, osInfoRaw, osInfoErr := collectOSInformationUnix(ctx)
|
||||||
|
|
||||||
|
var memoryMaximum, memoryCurrent, fileDescriptorMaximum, fileDescriptorCurrent uint64
|
||||||
|
var osSystem, name, osVersion, osRelease, architecture string
|
||||||
|
gerror := SystemInformationGeneralError{}
|
||||||
|
|
||||||
if memoryInfoErr != nil {
|
if memoryInfoErr != nil {
|
||||||
raw := RawSystemInformation(osInfoRaw, memoryInfoRaw, fdInfoRaw, disksRaw)
|
gerror.MemoryInformationError = SystemInformationError{
|
||||||
return nil, raw, memoryInfoErr
|
Err: memoryInfoErr,
|
||||||
|
RawInfo: memoryInfoRaw,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
memoryMaximum = memoryInfo.MemoryMaximum
|
||||||
|
memoryCurrent = memoryInfo.MemoryCurrent
|
||||||
}
|
}
|
||||||
|
|
||||||
if fdInfoErr != nil {
|
if fdInfoErr != nil {
|
||||||
raw := RawSystemInformation(osInfoRaw, memoryInfoRaw, fdInfoRaw, disksRaw)
|
gerror.FileDescriptorsInformationError = SystemInformationError{
|
||||||
return nil, raw, fdInfoErr
|
Err: fdInfoErr,
|
||||||
|
RawInfo: fdInfoRaw,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fileDescriptorMaximum = fdInfo.FileDescriptorMaximum
|
||||||
|
fileDescriptorCurrent = fdInfo.FileDescriptorCurrent
|
||||||
}
|
}
|
||||||
|
|
||||||
if diskErr != nil {
|
if diskErr != nil {
|
||||||
raw := RawSystemInformation(osInfoRaw, memoryInfoRaw, fdInfoRaw, disksRaw)
|
gerror.DiskVolumeInformationError = SystemInformationError{
|
||||||
return nil, raw, diskErr
|
Err: diskErr,
|
||||||
|
RawInfo: disksRaw,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if osInfoErr != nil {
|
if osInfoErr != nil {
|
||||||
raw := RawSystemInformation(osInfoRaw, memoryInfoRaw, fdInfoRaw, disksRaw)
|
gerror.OperatingSystemInformationError = SystemInformationError{
|
||||||
return nil, raw, osInfoErr
|
Err: osInfoErr,
|
||||||
|
RawInfo: osInfoRaw,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
osSystem = osInfo.OsSystem
|
||||||
|
name = osInfo.Name
|
||||||
|
osVersion = osInfo.OsVersion
|
||||||
|
osRelease = osInfo.OsRelease
|
||||||
|
architecture = osInfo.Architecture
|
||||||
}
|
}
|
||||||
|
|
||||||
return NewSystemInformation(
|
cloudflaredVersion := collector.version
|
||||||
memoryInfo.MemoryMaximum,
|
info := NewSystemInformation(
|
||||||
memoryInfo.MemoryCurrent,
|
memoryMaximum,
|
||||||
fdInfo.FileDescriptorMaximum,
|
memoryCurrent,
|
||||||
fdInfo.FileDescriptorCurrent,
|
fileDescriptorMaximum,
|
||||||
osInfo.OsSystem,
|
fileDescriptorCurrent,
|
||||||
osInfo.Name,
|
osSystem,
|
||||||
osInfo.OsVersion,
|
name,
|
||||||
osInfo.OsRelease,
|
osVersion,
|
||||||
osInfo.Architecture,
|
osRelease,
|
||||||
collector.version,
|
architecture,
|
||||||
|
cloudflaredVersion,
|
||||||
|
runtime.Version(),
|
||||||
|
runtime.GOARCH,
|
||||||
disks,
|
disks,
|
||||||
), "", nil
|
)
|
||||||
|
|
||||||
|
return info, gerror
|
||||||
}
|
}
|
||||||
|
|
||||||
func collectMemoryInformation(ctx context.Context) (*MemoryInformation, string, error) {
|
func collectMemoryInformation(ctx context.Context) (*MemoryInformation, string, error) {
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -21,41 +22,80 @@ func NewSystemCollectorImpl(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (collector *SystemCollectorImpl) Collect(ctx context.Context) (*SystemInformation, string, error) {
|
func (collector *SystemCollectorImpl) Collect(ctx context.Context) (*SystemInformation, error) {
|
||||||
memoryInfo, memoryInfoRaw, memoryInfoErr := collectMemoryInformation(ctx)
|
memoryInfo, memoryInfoRaw, memoryInfoErr := collectMemoryInformation(ctx)
|
||||||
fdInfo, fdInfoRaw, fdInfoErr := collectFileDescriptorInformation(ctx)
|
fdInfo, fdInfoRaw, fdInfoErr := collectFileDescriptorInformation(ctx)
|
||||||
disks, disksRaw, diskErr := collectDiskVolumeInformationUnix(ctx)
|
disks, disksRaw, diskErr := collectDiskVolumeInformationUnix(ctx)
|
||||||
osInfo, osInfoRaw, osInfoErr := collectOSInformationUnix(ctx)
|
osInfo, osInfoRaw, osInfoErr := collectOSInformationUnix(ctx)
|
||||||
|
|
||||||
|
var memoryMaximum, memoryCurrent, fileDescriptorMaximum, fileDescriptorCurrent uint64
|
||||||
|
var osSystem, name, osVersion, osRelease, architecture string
|
||||||
|
|
||||||
|
err := SystemInformationGeneralError{
|
||||||
|
OperatingSystemInformationError: nil,
|
||||||
|
MemoryInformationError: nil,
|
||||||
|
FileDescriptorsInformationError: nil,
|
||||||
|
DiskVolumeInformationError: nil,
|
||||||
|
}
|
||||||
|
|
||||||
if memoryInfoErr != nil {
|
if memoryInfoErr != nil {
|
||||||
return nil, RawSystemInformation(osInfoRaw, memoryInfoRaw, fdInfoRaw, disksRaw), memoryInfoErr
|
err.MemoryInformationError = SystemInformationError{
|
||||||
|
Err: memoryInfoErr,
|
||||||
|
RawInfo: memoryInfoRaw,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
memoryMaximum = memoryInfo.MemoryMaximum
|
||||||
|
memoryCurrent = memoryInfo.MemoryCurrent
|
||||||
}
|
}
|
||||||
|
|
||||||
if fdInfoErr != nil {
|
if fdInfoErr != nil {
|
||||||
return nil, RawSystemInformation(osInfoRaw, memoryInfoRaw, fdInfoRaw, disksRaw), fdInfoErr
|
err.FileDescriptorsInformationError = SystemInformationError{
|
||||||
|
Err: fdInfoErr,
|
||||||
|
RawInfo: fdInfoRaw,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fileDescriptorMaximum = fdInfo.FileDescriptorMaximum
|
||||||
|
fileDescriptorCurrent = fdInfo.FileDescriptorCurrent
|
||||||
}
|
}
|
||||||
|
|
||||||
if diskErr != nil {
|
if diskErr != nil {
|
||||||
return nil, RawSystemInformation(osInfoRaw, memoryInfoRaw, fdInfoRaw, disksRaw), diskErr
|
err.DiskVolumeInformationError = SystemInformationError{
|
||||||
|
Err: diskErr,
|
||||||
|
RawInfo: disksRaw,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if osInfoErr != nil {
|
if osInfoErr != nil {
|
||||||
return nil, RawSystemInformation(osInfoRaw, memoryInfoRaw, fdInfoRaw, disksRaw), osInfoErr
|
err.OperatingSystemInformationError = SystemInformationError{
|
||||||
|
Err: osInfoErr,
|
||||||
|
RawInfo: osInfoRaw,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
osSystem = osInfo.OsSystem
|
||||||
|
name = osInfo.Name
|
||||||
|
osVersion = osInfo.OsVersion
|
||||||
|
osRelease = osInfo.OsRelease
|
||||||
|
architecture = osInfo.Architecture
|
||||||
}
|
}
|
||||||
|
|
||||||
return NewSystemInformation(
|
cloudflaredVersion := collector.version
|
||||||
memoryInfo.MemoryMaximum,
|
info := NewSystemInformation(
|
||||||
memoryInfo.MemoryCurrent,
|
memoryMaximum,
|
||||||
fdInfo.FileDescriptorMaximum,
|
memoryCurrent,
|
||||||
fdInfo.FileDescriptorCurrent,
|
fileDescriptorMaximum,
|
||||||
osInfo.OsSystem,
|
fileDescriptorCurrent,
|
||||||
osInfo.Name,
|
osSystem,
|
||||||
osInfo.OsVersion,
|
name,
|
||||||
osInfo.OsRelease,
|
osVersion,
|
||||||
osInfo.Architecture,
|
osRelease,
|
||||||
collector.version,
|
architecture,
|
||||||
|
cloudflaredVersion,
|
||||||
|
runtime.Version(),
|
||||||
|
runtime.GOARCH,
|
||||||
disks,
|
disks,
|
||||||
), "", nil
|
)
|
||||||
|
|
||||||
|
return info, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func collectFileDescriptorInformation(ctx context.Context) (
|
func collectFileDescriptorInformation(ctx context.Context) (
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -22,41 +23,70 @@ func NewSystemCollectorImpl(
|
||||||
version,
|
version,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func (collector *SystemCollectorImpl) Collect(ctx context.Context) (*SystemInformation, string, error) {
|
|
||||||
|
func (collector *SystemCollectorImpl) Collect(ctx context.Context) (*SystemInformation, error) {
|
||||||
memoryInfo, memoryInfoRaw, memoryInfoErr := collectMemoryInformation(ctx)
|
memoryInfo, memoryInfoRaw, memoryInfoErr := collectMemoryInformation(ctx)
|
||||||
disks, disksRaw, diskErr := collectDiskVolumeInformation(ctx)
|
disks, disksRaw, diskErr := collectDiskVolumeInformation(ctx)
|
||||||
osInfo, osInfoRaw, osInfoErr := collectOSInformation(ctx)
|
osInfo, osInfoRaw, osInfoErr := collectOSInformation(ctx)
|
||||||
|
|
||||||
|
var memoryMaximum, memoryCurrent, fileDescriptorMaximum, fileDescriptorCurrent uint64
|
||||||
|
var osSystem, name, osVersion, osRelease, architecture string
|
||||||
|
|
||||||
|
err := SystemInformationGeneralError{
|
||||||
|
OperatingSystemInformationError: nil,
|
||||||
|
MemoryInformationError: nil,
|
||||||
|
FileDescriptorsInformationError: nil,
|
||||||
|
DiskVolumeInformationError: nil,
|
||||||
|
}
|
||||||
|
|
||||||
if memoryInfoErr != nil {
|
if memoryInfoErr != nil {
|
||||||
raw := RawSystemInformation(osInfoRaw, memoryInfoRaw, "", disksRaw)
|
err.MemoryInformationError = SystemInformationError{
|
||||||
return nil, raw, memoryInfoErr
|
Err: memoryInfoErr,
|
||||||
|
RawInfo: memoryInfoRaw,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
memoryMaximum = memoryInfo.MemoryMaximum
|
||||||
|
memoryCurrent = memoryInfo.MemoryCurrent
|
||||||
}
|
}
|
||||||
|
|
||||||
if diskErr != nil {
|
if diskErr != nil {
|
||||||
raw := RawSystemInformation(osInfoRaw, memoryInfoRaw, "", disksRaw)
|
err.DiskVolumeInformationError = SystemInformationError{
|
||||||
return nil, raw, diskErr
|
Err: diskErr,
|
||||||
|
RawInfo: disksRaw,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if osInfoErr != nil {
|
if osInfoErr != nil {
|
||||||
raw := RawSystemInformation(osInfoRaw, memoryInfoRaw, "", disksRaw)
|
err.OperatingSystemInformationError = SystemInformationError{
|
||||||
return nil, raw, osInfoErr
|
Err: osInfoErr,
|
||||||
|
RawInfo: osInfoRaw,
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
osSystem = osInfo.OsSystem
|
||||||
|
name = osInfo.Name
|
||||||
|
osVersion = osInfo.OsVersion
|
||||||
|
osRelease = osInfo.OsRelease
|
||||||
|
architecture = osInfo.Architecture
|
||||||
}
|
}
|
||||||
|
|
||||||
return NewSystemInformation(
|
cloudflaredVersion := collector.version
|
||||||
memoryInfo.MemoryMaximum,
|
info := NewSystemInformation(
|
||||||
memoryInfo.MemoryCurrent,
|
memoryMaximum,
|
||||||
// For windows we leave both the fileDescriptorMaximum and fileDescriptorCurrent with zero
|
memoryCurrent,
|
||||||
// since there is no obvious way to get this information.
|
fileDescriptorMaximum,
|
||||||
0,
|
fileDescriptorCurrent,
|
||||||
0,
|
osSystem,
|
||||||
osInfo.OsSystem,
|
name,
|
||||||
osInfo.Name,
|
osVersion,
|
||||||
osInfo.OsVersion,
|
osRelease,
|
||||||
osInfo.OsRelease,
|
architecture,
|
||||||
osInfo.Architecture,
|
cloudflaredVersion,
|
||||||
collector.version,
|
runtime.Version(),
|
||||||
|
runtime.GOARCH,
|
||||||
disks,
|
disks,
|
||||||
), "", nil
|
)
|
||||||
|
|
||||||
|
return info, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func collectMemoryInformation(ctx context.Context) (*MemoryInformation, string, error) {
|
func collectMemoryInformation(ctx context.Context) (*MemoryInformation, string, error) {
|
||||||
|
|
|
@ -29,7 +29,7 @@ var Runtime = "host"
|
||||||
|
|
||||||
func GetMetricsDefaultAddress(runtimeType string) string {
|
func GetMetricsDefaultAddress(runtimeType string) string {
|
||||||
// When issuing the diagnostic command we may have to reach a server that is
|
// When issuing the diagnostic command we may have to reach a server that is
|
||||||
// running in a virtual enviroment and in that case we must bind to 0.0.0.0
|
// running in a virtual environment and in that case we must bind to 0.0.0.0
|
||||||
// otherwise the server won't be reachable.
|
// otherwise the server won't be reachable.
|
||||||
switch runtimeType {
|
switch runtimeType {
|
||||||
case "virtual":
|
case "virtual":
|
||||||
|
|
Loading…
Reference in New Issue