Skip to content

Commit

Permalink
Some refactor around license.
Browse files Browse the repository at this point in the history
Trying to put responsibility in the right places.
  • Loading branch information
KacperPerschke committed Nov 5, 2024
1 parent 56a1722 commit 9fbf1c5
Show file tree
Hide file tree
Showing 3 changed files with 104 additions and 63 deletions.
19 changes: 19 additions & 0 deletions artifactory/system.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ package artifactory

import (
"encoding/json"
"slices"
"strings"
)

const (
Expand Down Expand Up @@ -67,6 +69,23 @@ type LicenseInfo struct {
ValidThrough string `json:"validThrough"`
LicensedTo string `json:"licensedTo"`
NodeId string
ValidSeconds int64 // It will be calculated in the ‘collector’ package.
}

func (l LicenseInfo) NormalizedLicenseType() string {
return strings.ToLower(l.Type)
}

func (l LicenseInfo) IsOSS() bool {
var afOSSLicenseTypes = []string{
`community edition for c/c++`,
`jcr edition`,
`oss`,
}
return slices.Contains(
afOSSLicenseTypes,
l.NormalizedLicenseType(),
)
}

// FetchLicense makes the API call to license endpoint and returns LicenseInfo
Expand Down
44 changes: 3 additions & 41 deletions collector/collector.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package collector

import (
"strings"

"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/common/version"
)
Expand Down Expand Up @@ -134,52 +132,16 @@ func (e *Exporter) Collect(ch chan<- prometheus.Metric) {
func (e *Exporter) scrape(ch chan<- prometheus.Metric) (up float64) {
e.totalScrapes.Inc()

// Collect License info
var licenseType string
license, err := e.client.FetchLicense()
if err != nil {
e.totalAPIErrors.Inc()
return 0
}
licenseType = strings.ToLower(license.Type)
// Some API endpoints are not available in OSS
if licenseType != "oss" && licenseType != "jcr edition" && licenseType != "community edition for c/c++" {
for metricName, metric := range securityMetrics {
switch metricName {
case "users":
err := e.exportUsersCount(metricName, metric, ch)
if err != nil {
return 0
}
case "groups":
err := e.exportGroups(metricName, metric, ch)
if err != nil {
return 0
}
case "certificates":
err := e.exportCertificates(metricName, metric, ch)
if err != nil {
return 0
}
}
}
err = e.exportReplications(ch)
if err != nil {
return 0
}
}

// Collect and export open metrics
if e.optionalMetrics.OpenMetrics {
err = e.exportOpenMetrics(ch)
err := e.exportOpenMetrics(ch)
if err != nil {
return 0
}
}

// Collect and export system metrics
err = e.exportSystem(license, ch)
if err != nil {
if err := e.exportSystem(ch); err != nil {
return 0
}

Expand All @@ -200,7 +162,7 @@ func (e *Exporter) scrape(ch chan<- prometheus.Metric) (up float64) {

// Get Downloaded and Created items for all repo in the last 1 and 5 minutes and add it to repoSummaryList
if e.optionalMetrics.Artifacts {
repoSummaryList, err = e.getTotalArtifacts(repoSummaryList)
repoSummaryList, err := e.getTotalArtifacts(repoSummaryList)
if err != nil {
return 0
}
Expand Down
104 changes: 82 additions & 22 deletions collector/system.go
Original file line number Diff line number Diff line change
@@ -1,16 +1,76 @@
package collector

import (
"strings"
"time"

"github.com/prometheus/client_golang/prometheus"

"github.com/peimanja/artifactory_exporter/artifactory"
)

func (e *Exporter) exportSystem(license artifactory.LicenseInfo, ch chan<- prometheus.Metric) error {
health, err := e.client.FetchHealth()
var afOSSLicenseTypes = []string{
`oss`,
`jcr edition`,
`community edition for c/c++`,
}

func collectLicense(e *Exporter, ch chan<- prometheus.Metric) (artifactory.LicenseInfo, error) {
retErr := func(err error) (artifactory.LicenseInfo, error) {
return artifactory.LicenseInfo{}, err
}

license, err := e.client.FetchLicense()
if err != nil {
return retErr(err)
}

if !license.IsOSS() { // Some endpoints are only available commercially.
for metricName, metric := range securityMetrics {
switch metricName {
case "users":
err := e.exportUsersCount(metricName, metric, ch)
if err != nil {
return retErr(err)
}
case "groups":
err := e.exportGroups(metricName, metric, ch)
if err != nil {
return retErr(err)
}
case "certificates":
err := e.exportCertificates(metricName, metric, ch)
if err != nil {
return retErr(err)
}
}
}
if err := e.exportReplications(ch); err != nil {
return retErr(err)
}
}

licenseValidSeconds := func() int64 {
if license.IsOSS() {
return 0
}
validThroughTime, err := time.Parse("Jan 2, 2006", license.ValidThrough)
if err != nil {
e.logger.Warn(
"Couldn't parse Artifactory license ValidThrough",
"err", err.Error(),
)
return 0 // We deliberately ignore the error in order to maintain continuity.
}
validThroughEpoch := validThroughTime.Unix()
timeNowEpoch := time.Now().Unix()
return validThroughEpoch - timeNowEpoch
}
license.ValidSeconds = licenseValidSeconds()
return license, nil
}

func (e *Exporter) exportSystem(ch chan<- prometheus.Metric) error {
healthInfo, err := e.client.FetchHealth()
if err != nil {
e.logger.Error(
"Couldn't scrape Artifactory when fetching system/ping",
Expand All @@ -28,32 +88,32 @@ func (e *Exporter) exportSystem(license artifactory.LicenseInfo, ch chan<- prome
e.totalAPIErrors.Inc()
return err
}
licenseInfo, err := collectLicense(e, ch)
if err != nil {
e.logger.Error(
"Couldn't scrape Artifactory when fetching system/license",
"err", err.Error(),
)
e.totalAPIErrors.Inc()
return err
}

licenseType := strings.ToLower(license.Type)
for metricName, metric := range systemMetrics {
switch metricName {
case "healthy":
ch <- prometheus.MustNewConstMetric(metric, prometheus.GaugeValue, convArtiToPromBool(health.Healthy), health.NodeId)
ch <- prometheus.MustNewConstMetric(metric, prometheus.GaugeValue, convArtiToPromBool(healthInfo.Healthy), healthInfo.NodeId)
case "version":
ch <- prometheus.MustNewConstMetric(metric, prometheus.GaugeValue, 1, buildInfo.Version, buildInfo.Revision, buildInfo.NodeId)
case "license":
var validThrough float64
timeNow := float64(time.Now().Unix())
switch licenseType {
case "oss", "jcr edition", "community edition for c/c++":
validThrough = timeNow
default:
if validThroughTime, err := time.Parse("Jan 2, 2006", license.ValidThrough); err != nil {
e.logger.Warn(
"Couldn't parse Artifactory license ValidThrough",
"err", err.Error(),
)
validThrough = timeNow
} else {
validThrough = float64(validThroughTime.Unix())
}
}
ch <- prometheus.MustNewConstMetric(metric, prometheus.GaugeValue, validThrough-timeNow, licenseType, license.LicensedTo, license.ValidThrough, license.NodeId)
ch <- prometheus.MustNewConstMetric(
metric,
prometheus.GaugeValue,
float64(licenseInfo.ValidSeconds), //float
licenseInfo.NormalizedLicenseType(),
licenseInfo.LicensedTo,
licenseInfo.ValidThrough,
licenseInfo.NodeId,
)
}
}
return nil
Expand Down

0 comments on commit 9fbf1c5

Please sign in to comment.