Skip to content

Commit

Permalink
SetValue can handle all primitive types, except complex and uintptr.
Browse files Browse the repository at this point in the history
Add tests for each case.
  • Loading branch information
benjaminbear committed Oct 17, 2019
1 parent ebf6364 commit 0457671
Show file tree
Hide file tree
Showing 14 changed files with 1,436 additions and 241 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,5 @@ _testmain.go
*.exe
*.test
*.prof

.idea/
35 changes: 35 additions & 0 deletions .gitlab-ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
include:
- project: "infrastructure/templates"
ref: master
file: "/.golang.yml"
- project: "infrastructure/templates"
ref: master
file: "/.runner-tags.yml"

image: ${INFRA_GOLANG_IMAGE}

stages:
- test

golangci-lint:
stage: test
before_script:
- export GO111MODULE=on
- go mod download
script:
- go version
- golangci-lint run ./...
extends: .INFRA_RUNNER_TAGS_K8S

testing:
stage: test
coverage: '/^total:\t+\(statements\)\t+(\d+\.\d+)%/'
before_script:
- export GO111MODULE=on
- go mod download
script:
- go version
- go test ./... -coverprofile cover.out
- go tool cover -func cover.out
extends: .INFRA_RUNNER_TAGS_K8S

16 changes: 16 additions & 0 deletions .golangci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
run:
deadline: 5m
tests: false

linters-settings:
errcheck:
# ignore stupid FlagCheck that is already checked, rest is default
ignore: fmt:.*

linters:
enable-all: true
fast: false

issues:
max-issues-per-linter: 50
max-same-issues: 50
19 changes: 19 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
language: go

env:
- GO111MODULE=on

git:
depth: 1

go:
- 1.12.x
- 1.13.x

before_script:
- go install github.com/golangci/golangci-lint/cmd/golangci-lint

script:
- golangci-lint run ./...
- go test ./... -coverprofile cover.out
- go tool cover -func cover.out
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
Copyright (c) 2016, Paessler AG <[email protected]>
Copyright (c) 2019, Paessler AG <[email protected]>
All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
Expand Down
148 changes: 118 additions & 30 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
# go-prtg-api
# go-prtg-sensor-api
API for writing PRTG custom sensors in Go.

## Example
This simple exampe sensor sends an HTTP request to http://paessler.com
[![Build Status](https://travis-ci.org/PRTG/go-prtg-sensor-api.svg "Travis CI status")](https://travis-ci.org/PRTG/go-prtg-sensor-api)
[![GoDoc](https://godoc.org/github.com/PRTG/go-prtg-sensor-api?status.svg)](https://godoc.org/github.com/PRTG/go-prtg-sensor-api)
[![Go Report Card](https://goreportcard.com/badge/github.com/PRTG/go-prtg-sensor-api)](https://goreportcard.com/report/PRTG/go-prtg-sensor-api/)

## Example EXE Sensor
This simple example sensor sends an HTTP request to http://paessler.com
and returns two channels:
- `Response time` - time it takes to perform the request and read the body
- `Bytes read` - number of bytes the body contained
Expand All @@ -13,54 +17,57 @@ package main
import (
"fmt"
"io/ioutil"
"log"
"net/http"
"time"

"github.com/PaesslerAG/go-prtg-sensor-api"
"github.com/PRTG/go-prtg-sensor-api"
)

func main() {
// Create empty response and log start time
r := &prtg.SensorResponse{}
// Initiate Sensor instance
sensor := prtg.New()

// Log start time
start := time.Now()
// Perform HTTP request
resp, err := http.Get("http://paessler.com")
if err != nil {
r.PRTG.Error = "1"
r.PRTG.Text = err.Error()
fmt.Println(r.String())
sensor.SetError(true)
sensor.SetSensorText(err.Error())
json, err := sensor.MarshalToString()
if err != nil {
log.Fatal(err)
}
fmt.Println(json)
return
}
// Read the response
buffer, err := ioutil.ReadAll(resp.Body)
if err != nil {
r.PRTG.Error = "1"
r.PRTG.Text = err.Error()
fmt.Println(r.String())
sensor.SetError(true)
sensor.SetSensorText(err.Error())
json, err := sensor.MarshalToString()
if err != nil {
log.Fatal(err)
}
fmt.Println(json)
return
}
// Evaluate results
responseTime := time.Since(start)
responseBytes := len(buffer)

// Response time channel
r.AddChannel(prtg.SensorChannel{
Channel: "Response time",
Value: fmt.Sprintf("%f", responseTime.Seconds()*1000),
Float: 1,
ShowChart: 1,
ShowTable: 1,
Unit: prtg.UnitTimeResponse,
})
sensor.AddChannel("Response time").SetValue(responseTime.Seconds() * 1000).SetUnit(prtg.TimeResponse)
// Bytes read channel
r.AddChannel(prtg.SensorChannel{
Channel: "Bytes read",
Value: fmt.Sprintf("%d", responseBytes),
ShowChart: 1,
ShowTable: 1,
Unit: prtg.UnitBytesFile,
})

fmt.Println(r.String())
sensor.AddChannel("Bytes read").SetValue(responseBytes).SetUnit(prtg.BytesFile)

json, err := sensor.MarshalToString()
if err != nil {
log.Fatal(err)
}
fmt.Println(json)
}
```

Expand All @@ -74,6 +81,87 @@ To test this example in your PRTG installation follow these steps:
6. Under `EXE/Script` choose the `.exe` you copied in step 2
7. Done


## Example HTTP Data Advanced Sensor

This example sensor uses a http server to serve the sensor data, that can be pulled
by a http data advanced sensor.
- `Some value` - shows sample percentage value
- `Something` - shows if the Something service is up and running

The Sensor returns an error if "Something" is not ok.

```golang
package main

import (
"fmt"
"log"
"math/rand"
"net/http"

"github.com/PRTG/go-prtg-sensor-api"
)

func main() {
// Create a webserver listening on "/"
http.HandleFunc("/", reportStatus)
http.ListenAndServe(":8080", nil)
}

func reportStatus(w http.ResponseWriter, r *http.Request) {
// Initiate PRTG instance
sensor := prtg.New()

// Set sensor text
sensor.SetSensorText("This is a test sensor")

// Add a channel with a random float value in Percent
sensor.AddChannel("Some value").SetValue(rand.Float64() * 100).
SetUnit(prtg.Percent).SetMaxWarnLimit(80).SetMaxErrLimit(90)

// Take a look if Something is working
isUp, err := isSomethingUp()
// Create a Sensor that shows the uptime of Something
sensor.AddChannel("Something").SetValue(isUp).
SetValueLookup("prtg.standardlookups.connectionstate.stateonlineok")
// Create error message on sensor if the Something is down
if err != nil {
sensor.SetError(true)
sensor.SetSensorText("Test sensor error: " + err.Error())
}

// Create json output
json, err := sensor.MarshalToString()
if err != nil {
log.Fatal(err)
}

// Deliver to website
_, err = fmt.Fprint(w, json)
if err != nil {
log.Fatal(err)
}
}

func isSomethingUp() (bool, error) {
// Generate a "Thing" to watch, that is working in 90% of the time
if rand.Intn(10) > 1 {
return true, nil
}
return false, fmt.Errorf("the Something is struggling")
}
```

To test this example in your PRTG installation follow these steps:

1. Build the example
2. Run the binary
3. Go to PRTG web interface
4. Add Sensor to a device of your choice
5. Choose `HTTP Data Advanced` as sensor type
6. Under `URL` choose the ip of your device with the port `8080`
7. Done

## Documentation
- [godoc.org/github.com/PaesslerAG/go-prtg-sensor-api](https://godoc.org/github.com/PaesslerAG/go-prtg-sensor-api)
- [PRTG Manual](https://www.paessler.com/manuals/prtg/exe_script_advanced_sensor)
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
module github.com/PRTG/go-prtg-sensor-api

go 1.13
68 changes: 68 additions & 0 deletions prtg.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// Copyright (c) 2019, Paessler AG.
// All Rights Reserved

// Package PRTG implements the API for PRTG custom sensors.
// It provides all structs and constants needed to implement your own advanced exe sensor in Go.
package prtg

import (
"encoding/json"
)

// SensorStatus has the whole JSON object
type SensorResponse struct {
SensorResults SensorResults `json:"prtg"`
}

// SensorResults has all the channels
type SensorResults struct {
SensorChannels []SensorChannel `json:"result"`
Text string `json:"text,omitempty"`
Error string `json:"error,omitempty"`
}

type Sensor interface {
AddChannel(string) *SensorChannel
MarshalToString() (string, error)
SetSensorText(string) *SensorResults
SetError(bool) *SensorResults
}

// Creates the Sensor instance and returns the interface.
func New() Sensor {
return &SensorResults{}
}

// Name of the channel as displayed in user interfaces.
func (sr *SensorResults) AddChannel(channelName string) *SensorChannel {
newChan := SensorChannel{Channel: channelName}
sr.SensorChannels = append(sr.SensorChannels, newChan)

return &sr.SensorChannels[len(sr.SensorChannels)-1]
}

// Create a JSON string from the PRTG object
func (sr *SensorResults) MarshalToString() (string, error) {
bytes, err := json.Marshal(&SensorResponse{*sr})
return string(bytes), err
}

// Text the sensor returns in the Message field with every scanning interval.
// There can be one message per sensor, regardless of the number of channels.
// Default is OK.
func (sr *SensorResults) SetSensorText(text string) *SensorResults {
sr.Text = text
return sr
}

// If enabled, the sensor will return an error status.
// This element can be combined with the SensorText element in order to show an error message.
// Default is 0.
func (sr *SensorResults) SetError(err bool) *SensorResults {
sr.Error = "0"
if err {
sr.Error = "1"
}

return sr
}
Loading

0 comments on commit 0457671

Please sign in to comment.