github.com/cs3org/reva/v2@v2.27.7/pkg/mentix/exchangers/exporters/metrics/metrics.go (about)

     1  // Copyright 2018-2020 CERN
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  //
    15  // In applying this license, CERN does not waive the privileges and immunities
    16  // granted to it by virtue of its status as an Intergovernmental Organization
    17  // or submit itself to any jurisdiction.
    18  
    19  package metrics
    20  
    21  import (
    22  	"context"
    23  
    24  	"github.com/cs3org/reva/v2/pkg/mentix/config"
    25  	"github.com/cs3org/reva/v2/pkg/mentix/meshdata"
    26  	"github.com/pkg/errors"
    27  	"github.com/rs/zerolog"
    28  	"go.opencensus.io/stats"
    29  	"go.opencensus.io/stats/view"
    30  	"go.opencensus.io/tag"
    31  )
    32  
    33  // Metrics exposes various Mentix related metrics via Prometheus.
    34  type Metrics struct {
    35  	conf *config.Configuration
    36  	log  *zerolog.Logger
    37  
    38  	isScheduledStats *stats.Int64Measure
    39  }
    40  
    41  const (
    42  	keySiteID      = "site_id"
    43  	keySiteName    = "site"
    44  	keyServiceType = "service_type"
    45  )
    46  
    47  func (m *Metrics) initialize(conf *config.Configuration, log *zerolog.Logger) error {
    48  	if conf == nil {
    49  		return errors.Errorf("no configuration provided")
    50  	}
    51  	m.conf = conf
    52  
    53  	if log == nil {
    54  		return errors.Errorf("no logger provided")
    55  	}
    56  	m.log = log
    57  
    58  	if err := m.registerMetrics(); err != nil {
    59  		return errors.Wrap(err, "error while registering metrics")
    60  	}
    61  
    62  	return nil
    63  }
    64  
    65  func (m *Metrics) registerMetrics() error {
    66  	// Create the OpenCensus statistics and a corresponding view
    67  	m.isScheduledStats = stats.Int64("site_is_scheduled", "A boolean metric which shows whether the given site is currently scheduled or not", stats.UnitDimensionless)
    68  	isScheduledView := &view.View{
    69  		Name:        m.isScheduledStats.Name(),
    70  		Description: m.isScheduledStats.Description(),
    71  		Measure:     m.isScheduledStats,
    72  		TagKeys:     []tag.Key{tag.MustNewKey(keySiteID), tag.MustNewKey(keySiteName), tag.MustNewKey(keyServiceType)},
    73  		Aggregation: view.LastValue(),
    74  	}
    75  
    76  	if err := view.Register(isScheduledView); err != nil {
    77  		return errors.Wrap(err, "unable to register the site schedule status metrics view")
    78  	}
    79  
    80  	return nil
    81  }
    82  
    83  // Update is used to update/expose all metrics.
    84  func (m *Metrics) Update(meshData *meshdata.MeshData) error {
    85  	for _, site := range meshData.Sites {
    86  		if err := m.exportSiteMetrics(site); err != nil {
    87  			return errors.Wrapf(err, "error while exporting metrics for site '%v'", site.Name)
    88  		}
    89  	}
    90  
    91  	return nil
    92  }
    93  
    94  func (m *Metrics) exportSiteMetrics(site *meshdata.Site) error {
    95  	mutators := make([]tag.Mutator, 0)
    96  	mutators = append(mutators, tag.Insert(tag.MustNewKey(keySiteID), site.ID))
    97  	mutators = append(mutators, tag.Insert(tag.MustNewKey(keySiteName), site.Name))
    98  	mutators = append(mutators, tag.Insert(tag.MustNewKey(keyServiceType), "SCIENCEMESH_HCHECK"))
    99  
   100  	// Create a new context to serve the metrics
   101  	if ctx, err := tag.New(context.Background(), mutators...); err == nil {
   102  		isScheduled := int64(1)
   103  		if site.Downtimes.IsAnyActive() {
   104  			isScheduled = 0
   105  		}
   106  		stats.Record(ctx, m.isScheduledStats.M(isScheduled))
   107  	} else {
   108  		return errors.Wrap(err, "unable to create a context for the site schedule status metrics")
   109  	}
   110  
   111  	return nil
   112  }
   113  
   114  // New creates a new Metrics instance.
   115  func New(conf *config.Configuration, log *zerolog.Logger) (*Metrics, error) {
   116  	m := &Metrics{}
   117  	if err := m.initialize(conf, log); err != nil {
   118  		return nil, errors.Wrap(err, "unable to create new metrics object")
   119  	}
   120  	return m, nil
   121  }