Render Graph Image from curl

Attempting to download and save rendered image from docker config of Grafana 6.6 and latest render images. See docker-compose below. I can download rendered images from every browser I try, but when moving to a script, I can only download images using curl from the grafana public demo site.

Clearly I missing something something, any ideas on where to look for clues? I don’t see any issues in the logs when making requests.

The biggest difference that I attribute the likely cause is the inclusion of port definition in the url.

Is no port definition a requirement for the rendering container plugin?

docker-compose:

services:
grafana:
image: grafana/grafana:6.6.0
ports:
- “3000:3000”
volumes:
- /home/docker/grafana/data:/var/lib/grafana
environment:
GF_RENDERING_SERVER_URL: http://renderer:8081/render
GF_RENDERING_CALLBACK_URL: http://grafana:3000/
GF_LOG_FILTERS: rendering:debug
restart: on-failure
labels:
- com.centurylinklabs.watchtower.enable=true
- autoheal.stop.timeout=240
renderer:
image: grafana/grafana-image-renderer:latest
ports:
- 8081
restart: on-failure
labels:
- com.centurylinklabs.watchtower.enable=true
- autoheal.stop.timeout=240
environment:
ENABLE_METRICS: ‘true’

Curl script:

# Working
link = "https://play.grafana.org/render/d-solo/000000014/elasticsearch-metrics?orgId=1&from=1614791753702&to=1614793553702&var-NewFilter=1&panelId=1&width=1000&height=500&tz=America%2FLos_Angeles"
link = "http://play.grafana.org/render/d-solo/000000014/elasticsearch-metrics?orgId=1&from=1614791753702&to=1614793553702&var-NewFilter=1&panelId=1&width=1000&height=500&tz=America%2FLos_Angeles"

 #Fails on local grafana instance
#link = 'http://192.168.2.100:3000/render/d-solo/changeforprivacy/environment?orgId=1&from=1614772408477&to=1614794008477&panelId=12&width=1000&height=500&tz=America%2FLos_Angeles'
fileLog = '/config/run.log'

c = pycurl.Curl()
c.setopt(c.URL, link)
c.setopt(pycurl.MAXREDIRS, 50)
c.setopt(c.FOLLOWLOCATION, True)
c.setopt(pycurl.CONNECTTIMEOUT, 600)
c.setopt(pycurl.TIMEOUT, 600)
c.setopt(pycurl.CRLF, 0)
           
with open(fileOut, 'wb') as f:
   c.setopt(c.WRITEDATA, f)
   c.perform()
   c.close()

For the public grafana instance, I will get a valid png. For my local instance, I will get:

– NOTE: below document shortened for brevity:

  !(function() {
    if ('PerformanceLongTaskTiming' in window) {
      var g = (window.__tti = { e: [] });
      g.o = new PerformanceObserver(function(l) {
        g.e = g.e.concat(l.getEntries());
      });
      g.o.observe({ entryTypes: ['longtask'] });
    }
  })();

</script>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="viewport" content="width=device-width" />
<meta name="theme-color" content="#000" />

<title>Grafana</title>

<base href="/" />

<link
  rel="preload"
  href="public/fonts/roboto/RxZJdnzeo3R5zSexge8UUVtXRa8TVwTICgirnJhmVJw.woff2"
  as="font"
  crossorigin
/>

<link rel="icon" type="image/png" href="public/img/fav32.png" />
<link rel="apple-touch-icon" sizes="180x180" href="public/img/apple-touch-icon.png" />
<link rel="mask-icon" href="public/img/grafana_mask_icon.svg" color="#F05A28" />

<link rel="stylesheet" href="public/build/grafana.dark.b63fb8634611947fae1b.css" />

<script>
  performance.mark('css done blocking');
</script>
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black" />
<meta name="msapplication-TileColor" content="#2b5797" />
<meta name="msapplication-config" content="public/img/browserconfig.xml" />
.preloader { height: 100%; flex-direction: column; display: flex; justify-content: center; align-items: center; }
  .preloader__enter {
    opacity: 0;
    animation-name: preloader-fade-in;
    animation-iteration-count: 1;
    animation-duration: 0.9s;
    animation-delay: 1.35s;
    animation-fill-mode: forwards;
  }

  .preloader__bounce {
    text-align: center;
    animation-name: preloader-bounce;
    animation-duration: 0.9s;
    animation-iteration-count: infinite;
  }

    window.onload = function() {
      var preloader = document.getElementsByClassName("preloader");
      if (preloader.length) {
        preloader[0].className = "preloader preloader--done";
      }
    };
</script>




<script src="public/build/runtime.b63fb8634611947fae1b.js" type="text/javascript"></script>
<script src="public/build/angular~app.b63fb8634611947fae1b.js" type="text/javascript"></script>
<script src="public/build/app.b63fb8634611947fae1b.js" type="text/javascript"></script>
<script src="public/build/moment~app.b63fb8634611947fae1b.js" type="text/javascript"></script>
<script src="public/build/vendors~app.b63fb8634611947fae1b.js" type="text/javascript"></script>
<script>
  performance.mark('js done blocking');
</script>

Just to clarity the issue, it appears to be a requirement for https, is that intended by grafana?

head -n 1 test.png
?PNG

test.png

<html>
<head><title>308 Permanent Redirect</title></head>
<body>
<center><h1>308 Permanent Redirect</h1></center>
<hr><center>nginx/1.15.10</center>
</body>
</html>
  • Invalid result when http from local grafana instance
    curl -o test.png “HTTP-NEW-USER-SO-HAVETOCHANGE://192.168.2.23:3000/render/d-solo/
    changeforprivacy/energy?orgId=1&from=1614786991004&to=1614808591004&panelId=6&width=1000&height=500&tz=America%2FLos_Angeles” --max-redirs 10

test.png

<a href="/login">Found</a>.
 

Does no one use curl to render image?

Guess I should try a better product…

@mydefaultspamfilter you didn’t specify if you have the same issue as @ejonesejonesejones or not.

I know it’s frustrating to not get an answer to a question, especially when taking the time to provide quite a lot of information. Unfortunately sometimes it’s simply a matter of luck - whether someone who knows the answer happens to be looking at the forums at the right time. This is especially a problem with more niche topics.

I suspect in this case the difference in behavior between play.grafana.com and running a local instance is that play.grafana.com runs in anonymous mode and does not require authentication, whereas a local instance (unless configured to run in anonymous mode) does require authentication. So that will need to be added to the curl request. Otherwise Grafana will present you with a login page.

I don’t use the render functionality myself so am not sure exactly what auth will work. A browser cookie obviously will work (that’s why requests from the browser work), but that’s a bit of a pain to add reliably to a curl request. You can try an API key or basic auth.

Hope that helps steer you in the right direction.