Grafana datasource plugin for PRTG

Hi everyone,
I’ve created a new branch of the grafana-prtg plugin where you can log in without restarting Grafana or Docker. The previous login issue has been fixed in this version.

This branch contains a simplified version of the code – without streaming, tracing, or metrics – making it lightweight and easier to understand or extend.

:repeat_button: Feel free to clone and use it in your own projects.
:envelope_with_arrow: Feedback is welcome – feel free to reach out!


1 Like

will this plugin works if Grafana is installed on Windows server? I cloned and copied the files to the plugin folder but I can’t find the datasource.

Hi i dont get it to run on a Debian Linux Grafana Server.
What i have to do :confused:

There is a guide in this thread that shows you how to install it on Ubuntu server.

1 Like

i have the exact same thing on debian12 and it’s driving me crazy. Did you found a solution?

i found the issue. This plugin seems not working in 10.4.x only after 11.0?

Thanks for this great plugin.
I installed it on Grafana v11.5.2 and I have an issue when I tried to get data with *. In every field in the query, I see a placeholder that says, ‘Select Group/Device/Sensor or type *’. If I understand correctly, this means I should be able to type * to select everything, but when I do, I don’t get any data."

Hi everyone,

I thought I added the PRTG plugin to my Grafana but now I’m getting an error that the plugin can’t get information from PRTG I tried to connect but it always fails The grafana version I’m using is v12.2.0 and PRTG I’m using version 25.2.106

Restart Grafana, or pull the Grafana-prtg branch, and you can register again.

Hi Maxmaerkus,
Thank you for replying

Now I can add data source to Grafana

But there is a new problem that when I add new data source, the old data source cannot be used even though it was normal before. It’s like only 1 PRTG data source can exist on grafana

Read please Grafana datasource plugin for PRTG - #38 by mansion

Hi Max
Could you help me check issue time zone prtg connect grafana not match

Hi, Can you please tell me which time zone your PRTG server is running in?

I’m use time zone UTC +7 on Windows server running service PRTG and Ubuntu server running service Grafana

Hi,

I have installed and connected to my PRTG env.

Is there any dashboard templates? I dont got no time to create them myselves.

Guys, can you help me with a question:

I configured the plugin in my Grafana v12.0.2 (5bda17e7c1), the plugin is working but there are 2 things that are bothering me:

1 - When loading a complete dashboard, it always fails to display some panel. I always have to keep clicking refresh to load the rest.

2 - I’m using America/Sao_Paulo Brazil UTC-03:00 and the times are correct. However, any date/time range I select in Grafana, the panels don’t show the entire range. Example:

  • If I select the last 6 hours, the graph only shows the last 3 hours.

  • If I select the last 12 hours, the graph only shows the last 9 hours.

It seems to always cut off the first 3 hours.

@maxmarkusprogram can you help me with this?

I’m using Rocky Linux 8.10.

See the images below.

What is your datasource and is your datasource datetime column UTC?

Hello @yosiasz.
It’s America/Sao_Paulo, see the image below.

Guys, I found the problem :slight_smile:

Problem Summary

  • The plugin converted the time range twice:
  1. The range coming from Grafana was forced to UTC and,

  2. On the backend, the API converted it again to a hard-coded time zone (Europe/Berlin / Avrupa/Istanbul).

  • This double offset caused a ~3 hour cutoff at the beginning or end of the graphs when the environment was in America/Sao_Paulo (UTC-3).

  • The parser also converted times to time.Local, which could apply another offset depending on the host.

What I did

  1. Standardized the timezone via the datasource settings and defined UTC as the fallback.

  2. Removed .UTC() when calling the API — the API itself handles the conversion with the TZ configured.

  3. In the parser:

  • Parses in the configured timezone;

  • Returns always in UTC (consistent epoch);

  • No extra conversion to time.Local.

  1. In the historical call:
  • Uses the configured timezone (not hard-coded);

  • Reduced the range “padding” to ±5 min (previously ±1 h).


Altered excerpts

  1. pkg/plugin/parsetime.go

Main changes:

- var defaultTimezone = "Avrupa/Istanbul"
+ var defaultTimezone = "UTC" // safe fallback

+ func SetDefaultTimezone(timezone string) {
+ tz := strings.TrimSpace(timezone)
+ if tz == "" { backend.Logger.Info("No timezone provided..."); return }
+ if _, err := time.LoadLocation(tz); err != nil {
+ backend.Logger.Warn("Invalid timezone..., using UTC", "provided", tz, "error", err)
+ defaultTimezone = "UTC"; return
+ }
+ defaultTimezone = tz
+ backend.Logger.Info("Setting default timezone for date parsing", "timezone", defaultTimezone)
+ }

- // inside parsePRTGDateTime(...)
- destLoc := time.Local
+ // removed: does not convert to time.Local

- parsedTime, _ := time.ParseInLocation(layout, datetime, sourceLoc)
- utcTime := parsedTime.UTC()
- localTime := utcTime.In(destLoc)
- return localTime, strconv.FormatInt(localTime.Unix(), 10), nil
+ if t, err := time.ParseInLocation(layout, datetime, sourceLoc); err == nil {
+ tUTC := t.In(time.UTC) // normalizes to UTC
+ return tUTC, strconv.FormatInt(tUTC.Unix(), 10), nil
+ }

And also: when PRTG returns “date timeA - timeB” and timeB < timeA, add +1 day to cover midnight crossing.


  1. pkg/plugin/prtg_api.go → function GetHistoricalData(...)

Complete function change (key points highlighted):

func (a *Api) GetHistoricalData(sensorID string, startDate, endDate time.Time) (*PrtgHistoricalDataResponse, error) {

if sensorID == "" { return nil, fmt.Errorf("invalid query: missing sensor ID") }

- // old: TZ hard-coded and buffer ±1h
- loc, _ := time.LoadLocation("Europe/Berlin")
- localStartDate := startDate.In(loc).Add(-1 * time.Hour)
- localEndDate := endDate.In(loc).Add( 1 * time.Hour)

+ // new: uses TZ configured in settings; fallback UTC
+ loc, err := time.LoadLocation(defaultTimezone)
+ if err != nil { loc = time.UTC }
+ // small buffer only for edges
+ localStartDate := startDate.In(loc).Add(-5 * time.Minute)
+ localEndDate := endDate.In(loc).Add( 5 * time.Minute)

const format = "2006-01-02-15-04-05"

sdate := localStartDate.Format(format)

edate := localEndDate.Format(format)

// ... logic for choosing 'avg' preserved ...

// ... request and cache unchanged ...

log.DefaultLogger.Debug("Requesting historical data",
- "startDate", sdate, "endDate", edate, "avg", avg)
+ "startDate", sdate, "endDate", edate, "avg", avg, "timezone", defaultTimezone) 
}

  1. pkg/plugin/query.go

Ensure not passes .UTC() in the call:

- historicalData, err := d.api.GetHistoricalData(qm.SensorId, timeRange.From.UTC(), timeRange.To.UTC())
+ historicalData, err := d.api.GetHistoricalData(qm.SensorId, timeRange.From, timeRange.To)

Standardize timestamps to UTC when filling frames:

- timesRT = append(timesRT, timestamp)
+ timesRT = append(timesRT, timestamp.UTC())

and

- timesRT = []time.Time{timestamp}
+ timesRT = []time.Time{timestamp.UTC()}

Result

  • The selected interval in Grafana (e.g., Last 6/12 h) is now exactly respected;

  • Plugin logs now show Parsing datetime ... timezone=America/Sao_Paulo (or whatever you define in the settings);

  • No “cutoff” of ~3 h and no unexpected shifts between panes.

@maxmarkusprogram feel free to test and commit to Git if you want :slight_smile: