Approach for software version monitoring

Hi there,

I am new to this fabulous world of InfluxDB. I have a project for monitoring multiples PLCs like signals, status but also software versions and have an history of them.
A python script retrieves versions of different softwares and files from various locations (file product, code variable, etc.).

For the moment, all the versions I retrieve are build with number, ex : 1.2 or 1.2.3 or even 1.2.3.4
So it could have different depth (major revision, minor rev. release build, patch, …).

Initially, I used strings to store these values. I can see them in the Data Explore if I activate the “View Raw Data” mode, but in the graph I have no value. I don’t have this problem with non-string values. The same behaviour happen if I copy the query and use it in Grafana :

from(bucket: "mybucket_versions")
  |> range(start: v.timeRangeStart, stop: v.timeRangeStop)
  |> filter(fn: (r) => r["_measurement"] == "Version")
  |> filter(fn: (r) => r["SN"] == "SN/002025")
  |> filter(fn: (r) => r["System"] == "HMI")
  |> filter(fn: (r) => r["_field"] == "Version")
  |> aggregateWindow(every: v.windowPeriod, fn: last, createEmpty: false)
  |> yield(name: "last")

As a second step, I was wondering if it is not possible to store this in another way. Maybe with several fields (one for each level of the version)? The idea would be to be able to view the PLCs with such major and minor revision (without taking into account the lower levels).

Has anyone ever encountered a similar problem?

Thank you for your help !

Hi , yes you can definitely change the way you’re storing the version info splitting major/minor/build numbers as separate columns.

If you want that to be displayable visually in chronograph, those columns need to be of integer or maybe float.

@flo17 You need to change your visualization type to one that supports string values. The “Graph” visualization type requires numeric data to build line graphs. It doesn’t support string values. What type of visualization are you hoping to achieve?

To piggyback on @FixTestRepeat’s answer about splitting the semantic version into columns, it wouldn’t be hard at all. You can just use map() and strings.split(). The example below defines a custom function that does that to input data.

import "strings"

splitVersion = (tables=<-) => tables
    |> map(fn: (r) => {
        versionArr = strings.split(v: r._value, t: ".")
        return { r with major: int(v: versionArr[0]), minor: int(v: versionArr[1]), patch: int(v: versionArr[2]), build: int(v: versionArr[3]) }
    })

So if you have this input data:

_field _value
version 1.2.3.0
version 2.4.3.8
data
    |> splitVersion()

Would output:

_field _value major minor patch build
version 1.2.3.0 1 2 3 0
version 2.4.3.8 2 4 3 8
1 Like

@scott @FixTestRepeat Thank you for you detailled answer. Effectively the display issues seems to become to the fact that I use string and not numeric data.

I have to 2 main uses for the software version :

  • Display the version of the different software on the dedicated Grafana dashboard (one for each PLC)
    Ex :

    (but it seems that the stats module only accept number and not string). So if it is not possible to display unique string I will maybe use a table and list last measurement for each software.

  • Display the distribution of the different version across the machine (Bar Chart)

From an implementation point of view, it would better to create a measurement with multiple field for each version, wouldn’t be ?
Something like that :
Point(“Version”).tag(“SN”, sn).tag(“System”, “HMI”).field(“major”, version_major).field(“minor”, version_minor).field(“patch”, version_patch).field(“build”, version_build) and maybe even a field with the full version ?

So when I query the last measurement, it could be possible the retrieve one or more field for the version ?

I will try to implement these modification tomorrow and test it.

Edit : Just figure out, @scott, that your function is a Flux one. However if I store the major, minor,etc. version I could rebuild the final version with a Flux function (or use the full version field).

@flo17 I guess it just depends on whether or not you want to actually store the major, minor, etc. in on disk. In my opinion (this is only my opinion), you don’t need to since you already have the version stored in a field and you can just parse out the semantics at query time.