1// Copyright The OpenTelemetry Authors 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 15package obsreport 16 17import ( 18 "context" 19 20 "go.opencensus.io/stats" 21 "go.opencensus.io/tag" 22 "go.opentelemetry.io/otel" 23 "go.opentelemetry.io/otel/attribute" 24 "go.opentelemetry.io/otel/trace" 25 26 "go.opentelemetry.io/collector/config" 27 "go.opentelemetry.io/collector/config/configtelemetry" 28 "go.opentelemetry.io/collector/internal/obsreportconfig" 29 "go.opentelemetry.io/collector/internal/obsreportconfig/obsmetrics" 30 "go.opentelemetry.io/collector/receiver/scrapererror" 31) 32 33// ScraperContext adds the keys used when recording observability metrics to 34// the given context returning the newly created context. This context should 35// be used in related calls to the obsreport functions so metrics are properly 36// recorded. 37func ScraperContext( 38 ctx context.Context, 39 receiverID config.ComponentID, 40 scraper config.ComponentID, 41) context.Context { 42 ctx, _ = tag.New( 43 ctx, 44 tag.Upsert(obsmetrics.TagKeyReceiver, receiverID.String(), tag.WithTTL(tag.TTLNoPropagation)), 45 tag.Upsert(obsmetrics.TagKeyScraper, scraper.String(), tag.WithTTL(tag.TTLNoPropagation))) 46 47 return ctx 48} 49 50// Scraper is a helper to add observability to a component.Scraper. 51type Scraper struct { 52 receiverID config.ComponentID 53 scraper config.ComponentID 54 tracer trace.Tracer 55} 56 57// ScraperSettings are settings for creating a Scraper. 58type ScraperSettings struct { 59 ReceiverID config.ComponentID 60 Scraper config.ComponentID 61} 62 63// NewScraper creates a new Scraper. 64func NewScraper(cfg ScraperSettings) *Scraper { 65 return &Scraper{ 66 receiverID: cfg.ReceiverID, 67 scraper: cfg.Scraper, 68 tracer: otel.GetTracerProvider().Tracer(cfg.Scraper.String()), 69 } 70} 71 72// StartMetricsOp is called when a scrape operation is started. The 73// returned context should be used in other calls to the obsreport functions 74// dealing with the same scrape operation. 75func (s *Scraper) StartMetricsOp( 76 scraperCtx context.Context, 77) context.Context { 78 spanName := obsmetrics.ScraperPrefix + s.receiverID.String() + obsmetrics.NameSep + s.scraper.String() + obsmetrics.ScraperMetricsOperationSuffix 79 ctx, _ := s.tracer.Start(scraperCtx, spanName) 80 return ctx 81} 82 83// EndMetricsOp completes the scrape operation that was started with 84// StartMetricsOp. 85func (s *Scraper) EndMetricsOp( 86 scraperCtx context.Context, 87 numScrapedMetrics int, 88 err error, 89) { 90 numErroredMetrics := 0 91 if err != nil { 92 if partialErr, isPartial := err.(scrapererror.PartialScrapeError); isPartial { 93 numErroredMetrics = partialErr.Failed 94 } else { 95 numErroredMetrics = numScrapedMetrics 96 numScrapedMetrics = 0 97 } 98 } 99 100 span := trace.SpanFromContext(scraperCtx) 101 102 if obsreportconfig.Level != configtelemetry.LevelNone { 103 stats.Record( 104 scraperCtx, 105 obsmetrics.ScraperScrapedMetricPoints.M(int64(numScrapedMetrics)), 106 obsmetrics.ScraperErroredMetricPoints.M(int64(numErroredMetrics))) 107 } 108 109 // end span according to errors 110 if span.IsRecording() { 111 span.SetAttributes( 112 attribute.String(obsmetrics.FormatKey, string(config.MetricsDataType)), 113 attribute.Int64(obsmetrics.ScrapedMetricPointsKey, int64(numScrapedMetrics)), 114 attribute.Int64(obsmetrics.ErroredMetricPointsKey, int64(numErroredMetrics)), 115 ) 116 recordError(span, err) 117 } 118 119 span.End() 120} 121