diff --git a/pkg/winperfcounters/watcher.go b/pkg/winperfcounters/watcher.go index 20b91f0ffa14..7a4202fe30dd 100644 --- a/pkg/winperfcounters/watcher.go +++ b/pkg/winperfcounters/watcher.go @@ -46,6 +46,16 @@ type Watcher struct { MetricRep } +// NewWatcher creates new PerfCounterWatcher by provided parts of its path. +func NewWatcher(object, instance, counterName string) (PerfCounterWatcher, error) { + path := counterPath(object, instance, counterName) + counter, err := pdh.NewPerfCounter(path, true) + if err != nil { + return nil, fmt.Errorf("failed to create perf counter with path %v: %w", path, err) + } + return Watcher{Counter: counter}, nil +} + func (w Watcher) Path() string { return w.Counter.Path() } diff --git a/receiver/iisreceiver/config_generator.go b/receiver/iisreceiver/config_generator.go deleted file mode 100644 index 456971d0819a..000000000000 --- a/receiver/iisreceiver/config_generator.go +++ /dev/null @@ -1,211 +0,0 @@ -// Copyright The OpenTelemetry Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -//go:build windows -// +build windows - -package iisreceiver // import "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/iisreceiver" - -import ( - windowsapi "github.com/open-telemetry/opentelemetry-collector-contrib/pkg/winperfcounters" - "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/iisreceiver/internal/metadata" -) - -// getPerfCounters returns established PerfCounters for each metric. -func getScraperCfgs() []windowsapi.ObjectConfig { - return []windowsapi.ObjectConfig{ - { - Object: "Web Service", - Instances: []string{"_Total"}, - Counters: []windowsapi.CounterConfig{ - { - MetricRep: windowsapi.MetricRep{ - Name: "iis.connection.active", - }, - Name: "Current Connections", - }, - { - MetricRep: windowsapi.MetricRep{ - Name: "iis.network.io", - Attributes: map[string]string{ - "direction": "received", - }, - }, - Name: "Total Bytes Received", - }, - { - MetricRep: windowsapi.MetricRep{ - Name: "iis.network.io", - Attributes: map[string]string{ - "direction": "sent", - }, - }, - Name: "Total Bytes Sent", - }, - { - MetricRep: windowsapi.MetricRep{ - Name: "iis.connection.attempt.count", - }, - Name: "Total Connection Attempts (all instances)", - }, - { - MetricRep: windowsapi.MetricRep{ - Name: "iis.request.count", - Attributes: map[string]string{ - metadata.A.Request: "delete", - }, - }, - Name: "Total Delete Requests", - }, - { - MetricRep: windowsapi.MetricRep{ - Name: "iis.request.count", - Attributes: map[string]string{ - metadata.A.Request: "get", - }, - }, - - Name: "Total Get Requests", - }, - { - MetricRep: windowsapi.MetricRep{ - Name: "iis.request.count", - Attributes: map[string]string{ - metadata.A.Request: "head", - }, - }, - - Name: "Total Head Requests", - }, - { - MetricRep: windowsapi.MetricRep{ - Name: "iis.request.count", - Attributes: map[string]string{ - metadata.A.Request: "options", - }, - }, - - Name: "Total Options Requests", - }, - { - MetricRep: windowsapi.MetricRep{ - Name: "iis.request.count", - Attributes: map[string]string{ - metadata.A.Request: "post", - }, - }, - - Name: "Total Post Requests", - }, - { - MetricRep: windowsapi.MetricRep{ - Name: "iis.request.count", - Attributes: map[string]string{ - metadata.A.Request: "put", - }, - }, - - Name: "Total Put Requests", - }, - { - MetricRep: windowsapi.MetricRep{ - Name: "iis.request.count", - Attributes: map[string]string{ - metadata.A.Request: "trace", - }, - }, - - Name: "Total Trace Requests", - }, - { - MetricRep: windowsapi.MetricRep{ - Name: "iis.network.file.count", - Attributes: map[string]string{ - metadata.A.Direction: "received", - }, - }, - Name: "Total Files Received", - }, - { - MetricRep: windowsapi.MetricRep{ - Name: "iis.network.file.count", - Attributes: map[string]string{ - metadata.A.Direction: "sent", - }, - }, - Name: "Total Files Sent", - }, - { - MetricRep: windowsapi.MetricRep{ - Name: "iis.connection.anonymous", - }, - - Name: "Total Anonymous Users", - }, - { - MetricRep: windowsapi.MetricRep{ - Name: "iis.network.blocked", - }, - - Name: "Total blocked bandwidth bytes.", - }, - { - MetricRep: windowsapi.MetricRep{ - Name: "iis.uptime", - }, - - Name: "Service Uptime", - }, - }, - }, - { - Object: "HTTP Service Request Queues", - Instances: []string{"*"}, - Counters: []windowsapi.CounterConfig{ - { - MetricRep: windowsapi.MetricRep{ - Name: "iis.request.rejected", - }, - - Name: "RejectedRequests", - }, - { - MetricRep: windowsapi.MetricRep{ - Name: "iis.request.queue.count", - }, - - Name: "CurrentQueueSize", - }, - { - MetricRep: windowsapi.MetricRep{ - Name: "iis.request.queue.age.max", - }, - Name: "MaxQueueItemAge", - }, - }, - }, - { - Object: "Process", - Instances: []string{"_Total"}, - Counters: []windowsapi.CounterConfig{ - { - MetricRep: windowsapi.MetricRep{ - Name: "iis.thread.active", - }, - Name: "Thread Count", - }, - }, - }, - } -} diff --git a/receiver/iisreceiver/internal/metadata/recorder.go b/receiver/iisreceiver/internal/metadata/recorder.go deleted file mode 100644 index 365f89090d7f..000000000000 --- a/receiver/iisreceiver/internal/metadata/recorder.go +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright The OpenTelemetry Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package metadata // import "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/iisreceiver/internal/metadata" - -import ( - "go.opentelemetry.io/collector/pdata/pcommon" -) - -func (mb *MetricsBuilder) RecordAny(ts pcommon.Timestamp, val float64, name string, attributes map[string]string) { - switch name { - case "iis.connection.active": - mb.RecordIisConnectionActiveDataPoint(ts, int64(val)) - case "iis.connection.anonymous": - mb.RecordIisConnectionAnonymousDataPoint(ts, int64(val)) - case "iis.connection.attempt.count": - mb.RecordIisConnectionAttemptCountDataPoint(ts, int64(val)) - case "iis.network.blocked": - mb.RecordIisNetworkBlockedDataPoint(ts, int64(val)) - case "iis.network.file.count": - mb.RecordIisNetworkFileCountDataPoint(ts, int64(val), MapAttributeDirection[attributes[A.Direction]]) - case "iis.network.io": - mb.RecordIisNetworkIoDataPoint(ts, int64(val), MapAttributeDirection[attributes[A.Direction]]) - case "iis.request.count": - mb.RecordIisRequestCountDataPoint(ts, int64(val), MapAttributeRequest[attributes[A.Request]]) - case "iis.request.queue.age.max": - mb.RecordIisRequestQueueAgeMaxDataPoint(ts, int64(val)) - case "iis.request.queue.count": - mb.RecordIisRequestQueueCountDataPoint(ts, int64(val)) - case "iis.request.rejected": - mb.RecordIisRequestRejectedDataPoint(ts, int64(val)) - case "iis.thread.active": - mb.RecordIisThreadActiveDataPoint(ts, int64(val)) - case "iis.uptime": - mb.RecordIisUptimeDataPoint(ts, int64(val)) - } -} diff --git a/receiver/iisreceiver/recorder.go b/receiver/iisreceiver/recorder.go new file mode 100644 index 000000000000..5ab56e32db9b --- /dev/null +++ b/receiver/iisreceiver/recorder.go @@ -0,0 +1,114 @@ +// Copyright The OpenTelemetry Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +//go:build windows +// +build windows + +package iisreceiver // import "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/iisreceiver" + +import ( + "go.opentelemetry.io/collector/pdata/pcommon" + + "github.com/open-telemetry/opentelemetry-collector-contrib/receiver/iisreceiver/internal/metadata" +) + +type recordFunc = func(*metadata.MetricsBuilder, pcommon.Timestamp, float64) + +type perfCounterRecorderConf struct { + object string + instance string + recorders map[string]recordFunc +} + +var perfCounterRecorders = []perfCounterRecorderConf{ + { + object: "Web Service", + instance: "_Total", + recorders: map[string]recordFunc{ + "Current Connections": func(mb *metadata.MetricsBuilder, ts pcommon.Timestamp, val float64) { + mb.RecordIisConnectionActiveDataPoint(ts, int64(val)) + }, + "Total Bytes Received": func(mb *metadata.MetricsBuilder, ts pcommon.Timestamp, val float64) { + mb.RecordIisNetworkIoDataPoint(ts, int64(val), metadata.AttributeDirectionReceived) + }, + "Total Bytes Sent": func(mb *metadata.MetricsBuilder, ts pcommon.Timestamp, val float64) { + mb.RecordIisNetworkIoDataPoint(ts, int64(val), metadata.AttributeDirectionSent) + }, + "Total Connection Attempts (all instances)": func(mb *metadata.MetricsBuilder, ts pcommon.Timestamp, + val float64) { + mb.RecordIisConnectionAttemptCountDataPoint(ts, int64(val)) + }, + "Total Delete Requests": func(mb *metadata.MetricsBuilder, ts pcommon.Timestamp, val float64) { + mb.RecordIisRequestCountDataPoint(ts, int64(val), metadata.AttributeRequestDelete) + }, + "Total Get Requests": func(mb *metadata.MetricsBuilder, ts pcommon.Timestamp, val float64) { + mb.RecordIisRequestCountDataPoint(ts, int64(val), metadata.AttributeRequestGet) + }, + "Total Head Requests": func(mb *metadata.MetricsBuilder, ts pcommon.Timestamp, val float64) { + mb.RecordIisRequestCountDataPoint(ts, int64(val), metadata.AttributeRequestHead) + }, + "Total Options Requests": func(mb *metadata.MetricsBuilder, ts pcommon.Timestamp, val float64) { + mb.RecordIisRequestCountDataPoint(ts, int64(val), metadata.AttributeRequestOptions) + }, + "Total Post Requests": func(mb *metadata.MetricsBuilder, ts pcommon.Timestamp, val float64) { + mb.RecordIisRequestCountDataPoint(ts, int64(val), metadata.AttributeRequestPost) + }, + "Total Put Requests": func(mb *metadata.MetricsBuilder, ts pcommon.Timestamp, val float64) { + mb.RecordIisRequestCountDataPoint(ts, int64(val), metadata.AttributeRequestPut) + }, + "Total Trace Requests": func(mb *metadata.MetricsBuilder, ts pcommon.Timestamp, val float64) { + mb.RecordIisRequestCountDataPoint(ts, int64(val), metadata.AttributeRequestTrace) + }, + "Total Files Received": func(mb *metadata.MetricsBuilder, ts pcommon.Timestamp, val float64) { + mb.RecordIisNetworkFileCountDataPoint(ts, int64(val), metadata.AttributeDirectionReceived) + }, + "Total Files Sent": func(mb *metadata.MetricsBuilder, ts pcommon.Timestamp, val float64) { + mb.RecordIisNetworkFileCountDataPoint(ts, int64(val), metadata.AttributeDirectionSent) + }, + "Total Anonymous Users": func(mb *metadata.MetricsBuilder, ts pcommon.Timestamp, val float64) { + mb.RecordIisConnectionAnonymousDataPoint(ts, int64(val)) + }, + "Total blocked bandwidth bytes.": func(mb *metadata.MetricsBuilder, ts pcommon.Timestamp, val float64) { + mb.RecordIisNetworkBlockedDataPoint(ts, int64(val)) + }, + "Service Uptime": func(mb *metadata.MetricsBuilder, ts pcommon.Timestamp, val float64) { + mb.RecordIisUptimeDataPoint(ts, int64(val)) + }, + }, + }, + { + object: "HTTP Service Request Queues", + instance: "*", + recorders: map[string]recordFunc{ + "RejectedRequests": func(mb *metadata.MetricsBuilder, ts pcommon.Timestamp, val float64) { + mb.RecordIisRequestRejectedDataPoint(ts, int64(val)) + }, + "CurrentQueueSize": func(mb *metadata.MetricsBuilder, ts pcommon.Timestamp, val float64) { + mb.RecordIisRequestQueueCountDataPoint(ts, int64(val)) + }, + "MaxQueueItemAge": func(mb *metadata.MetricsBuilder, ts pcommon.Timestamp, val float64) { + mb.RecordIisRequestQueueAgeMaxDataPoint(ts, int64(val)) + }, + }, + }, + { + object: "Process", + instance: "_Total", + recorders: map[string]recordFunc{ + "Thread Count": func(mb *metadata.MetricsBuilder, ts pcommon.Timestamp, val float64) { + mb.RecordIisThreadActiveDataPoint(ts, int64(val)) + }, + }, + }, +} diff --git a/receiver/iisreceiver/scraper.go b/receiver/iisreceiver/scraper.go index c822be721bb0..42dd81e92399 100644 --- a/receiver/iisreceiver/scraper.go +++ b/receiver/iisreceiver/scraper.go @@ -19,7 +19,6 @@ package iisreceiver // import "github.com/open-telemetry/opentelemetry-collector import ( "context" - "fmt" "time" "go.opentelemetry.io/collector/component" @@ -35,31 +34,46 @@ import ( ) type iisReceiver struct { - params component.ReceiverCreateSettings - config *Config - consumer consumer.Metrics - watchers []winperfcounters.PerfCounterWatcher - metricBuilder *metadata.MetricsBuilder + params component.ReceiverCreateSettings + config *Config + consumer consumer.Metrics + watcherRecorders []watcherRecorder + metricBuilder *metadata.MetricsBuilder + + // for mocking + newWatcher func(string, string, string) (winperfcounters.PerfCounterWatcher, error) +} + +// watcherRecorder is a struct containing perf counter watcher along with corresponding value recorder. +type watcherRecorder struct { + watcher winperfcounters.PerfCounterWatcher + recorder recordFunc } // newIisReceiver returns an iisReceiver func newIisReceiver(params component.ReceiverCreateSettings, cfg *Config, consumer consumer.Metrics) *iisReceiver { - return &iisReceiver{params: params, config: cfg, consumer: consumer, metricBuilder: metadata.NewMetricsBuilder(cfg.Metrics)} + return &iisReceiver{ + params: params, + config: cfg, + consumer: consumer, + metricBuilder: metadata.NewMetricsBuilder(cfg.Metrics), + newWatcher: winperfcounters.NewWatcher, + } } // start builds the paths to the watchers func (rcvr *iisReceiver) start(ctx context.Context, host component.Host) error { - rcvr.watchers = []winperfcounters.PerfCounterWatcher{} + rcvr.watcherRecorders = []watcherRecorder{} var errors scrapererror.ScrapeErrors - for _, objCfg := range getScraperCfgs() { - objWatchers, err := objCfg.BuildPaths() - if err != nil { - errors.AddPartial(1, fmt.Errorf("some performance counters could not be initialized; %w", err)) - continue - } - for _, objWatcher := range objWatchers { - rcvr.watchers = append(rcvr.watchers, objWatcher) + for _, pcr := range perfCounterRecorders { + for perfCounterName, recorder := range pcr.recorders { + w, err := rcvr.newWatcher(pcr.object, pcr.instance, perfCounterName) + if err != nil { + errors.AddPartial(1, err) + continue + } + rcvr.watcherRecorders = append(rcvr.watcherRecorders, watcherRecorder{w, recorder}) } } @@ -71,19 +85,17 @@ func (rcvr *iisReceiver) scrape(ctx context.Context) (pmetric.Metrics, error) { var errs error now := pcommon.NewTimestampFromTime(time.Now()) - for _, watcher := range rcvr.watchers { - counterValues, err := watcher.ScrapeData() + for _, wr := range rcvr.watcherRecorders { + counterValues, err := wr.watcher.ScrapeData() if err != nil { rcvr.params.Logger.Warn("some performance counters could not be scraped; ", zap.Error(err)) continue } - var metricRep winperfcounters.MetricRep value := 0.0 for _, counterValue := range counterValues { value += counterValue.Value - metricRep = counterValue.MetricRep } - rcvr.metricBuilder.RecordAny(now, value, metricRep.Name, metricRep.Attributes) + wr.recorder(rcvr.metricBuilder, now, value) } return rcvr.metricBuilder.Emit(), errs @@ -92,8 +104,8 @@ func (rcvr *iisReceiver) scrape(ctx context.Context) (pmetric.Metrics, error) { // shutdown closes the watchers func (rcvr iisReceiver) shutdown(ctx context.Context) error { var errs error - for _, watcher := range rcvr.watchers { - err := watcher.Close() + for _, wr := range rcvr.watcherRecorders { + err := wr.watcher.Close() if err != nil { errs = multierr.Append(errs, err) } diff --git a/receiver/iisreceiver/scraper_test.go b/receiver/iisreceiver/scraper_test.go index 3354739dad2a..1d1d1368ee59 100644 --- a/receiver/iisreceiver/scraper_test.go +++ b/receiver/iisreceiver/scraper_test.go @@ -26,6 +26,7 @@ import ( "github.com/stretchr/testify/require" "go.opentelemetry.io/collector/component/componenttest" "go.opentelemetry.io/collector/consumer/consumertest" + "go.opentelemetry.io/collector/pdata/pcommon" "go.uber.org/zap" "go.uber.org/zap/zapcore" "go.uber.org/zap/zaptest/observer" @@ -45,8 +46,10 @@ func TestScrape(t *testing.T) { cfg, consumertest.NewNop(), ) + scraper.newWatcher = newMockWatcherFactory(nil, 1) - scraper.watchers = allFakePerfCounters() + err := scraper.start(context.Background(), componenttest.NewNopHost()) + require.NoError(t, err) actualMetrics, err := scraper.scrape(context.Background()) require.NoError(t, err) @@ -55,7 +58,7 @@ func TestScrape(t *testing.T) { expectedMetrics, err := golden.ReadMetrics(expectedFile) require.NoError(t, err) - require.NoError(t, scrapertest.CompareMetrics(actualMetrics, expectedMetrics)) + require.NoError(t, scrapertest.CompareMetrics(expectedMetrics, actualMetrics)) } func TestScrapeFailure(t *testing.T) { @@ -73,8 +76,15 @@ func TestScrapeFailure(t *testing.T) { ) expectedError := "failure to collect metric" - scraper.watchers = []winperfcounters.PerfCounterWatcher{ - newMockPerfCounter(fmt.Errorf(expectedError), 1, winperfcounters.MetricRep{Name: "iis.uptime"}), + mockWatcher, err := newMockWatcherFactory(fmt.Errorf(expectedError), 1)("", "", "") + require.NoError(t, err) + scraper.watcherRecorders = []watcherRecorder{ + { + watcher: mockWatcher, + recorder: func(mb *metadata.MetricsBuilder, ts pcommon.Timestamp, val float64) { + mb.RecordIisUptimeDataPoint(ts, int64(val)) + }, + }, } scraper.scrape(context.Background()) @@ -92,27 +102,13 @@ type mockPerfCounter struct { winperfcounters.MetricRep } -func allFakePerfCounters() []winperfcounters.PerfCounterWatcher { - return []winperfcounters.PerfCounterWatcher{ - newMockPerfCounter(nil, 1, winperfcounters.MetricRep{Name: "iis.connection.active"}), - newMockPerfCounter(nil, 1, winperfcounters.MetricRep{Name: "iis.connection.anonymous"}), - newMockPerfCounter(nil, 1, winperfcounters.MetricRep{Name: "iis.connection.attempt.count"}), - newMockPerfCounter(nil, 1, winperfcounters.MetricRep{Name: "iis.network.blocked"}), - newMockPerfCounter(nil, 1, winperfcounters.MetricRep{Name: "iis.network.file.count", Attributes: map[string]string{metadata.A.Direction: "received"}}), - newMockPerfCounter(nil, 1, winperfcounters.MetricRep{Name: "iis.network.io", Attributes: map[string]string{metadata.A.Direction: "sent"}}), - newMockPerfCounter(nil, 1, winperfcounters.MetricRep{Name: "iis.request.count", Attributes: map[string]string{metadata.A.Request: "get"}}), - newMockPerfCounter(nil, 1, winperfcounters.MetricRep{Name: "iis.request.queue.age.max"}), - newMockPerfCounter(nil, 1, winperfcounters.MetricRep{Name: "iis.request.queue.count"}), - newMockPerfCounter(nil, 1, winperfcounters.MetricRep{Name: "iis.request.rejected"}), - newMockPerfCounter(nil, 1, winperfcounters.MetricRep{Name: "iis.thread.active"}), - newMockPerfCounter(nil, 1, winperfcounters.MetricRep{Name: "iis.uptime"}), +func newMockWatcherFactory(watchErr error, value float64) func(string, string, + string) (winperfcounters.PerfCounterWatcher, error) { + return func(string, string, string) (winperfcounters.PerfCounterWatcher, error) { + return &mockPerfCounter{watchErr: watchErr, value: value}, nil } } -func newMockPerfCounter(watchErr error, value float64, metric winperfcounters.MetricRep) *mockPerfCounter { - return &mockPerfCounter{watchErr: watchErr, value: value, MetricRep: metric} -} - // Path func (mpc *mockPerfCounter) Path() string { return "" @@ -120,7 +116,7 @@ func (mpc *mockPerfCounter) Path() string { // ScrapeData func (mpc *mockPerfCounter) ScrapeData() ([]winperfcounters.CounterValue, error) { - return []winperfcounters.CounterValue{{Value: 1, MetricRep: mpc.MetricRep}}, mpc.watchErr + return []winperfcounters.CounterValue{{Value: 1}}, mpc.watchErr } // Close @@ -129,5 +125,5 @@ func (mpc *mockPerfCounter) Close() error { } func (mpc *mockPerfCounter) GetMetricRep() winperfcounters.MetricRep { - return mpc.MetricRep + return winperfcounters.MetricRep{} } diff --git a/receiver/iisreceiver/testdata/scraper/expected.json b/receiver/iisreceiver/testdata/scraper/expected.json index 0f715394f76d..af55778c3714 100644 --- a/receiver/iisreceiver/testdata/scraper/expected.json +++ b/receiver/iisreceiver/testdata/scraper/expected.json @@ -86,6 +86,19 @@ ], "startTimeUnixNano": "1649969943717902800", "timeUnixNano": "1649969943717902800" + }, + { + "asInt": "1", + "attributes": [ + { + "key": "direction", + "value": { + "stringValue": "sent" + } + } + ], + "startTimeUnixNano": "1649969943717902800", + "timeUnixNano": "1649969943717902800" } ], "isMonotonic": true @@ -98,6 +111,19 @@ "sum": { "aggregationTemporality": "AGGREGATION_TEMPORALITY_CUMULATIVE", "dataPoints": [ + { + "asInt": "1", + "attributes": [ + { + "key": "direction", + "value": { + "stringValue": "received" + } + } + ], + "startTimeUnixNano": "1649969943717902800", + "timeUnixNano": "1649969943717902800" + }, { "asInt": "1", "attributes": [ @@ -122,6 +148,19 @@ "sum": { "aggregationTemporality": "AGGREGATION_TEMPORALITY_CUMULATIVE", "dataPoints": [ + { + "asInt": "1", + "attributes": [ + { + "key": "request", + "value": { + "stringValue": "delete" + } + } + ], + "startTimeUnixNano": "1649969943717902800", + "timeUnixNano": "1649969943717902800" + }, { "asInt": "1", "attributes": [ @@ -134,6 +173,71 @@ ], "startTimeUnixNano": "1649969943717902800", "timeUnixNano": "1649969943717902800" + }, + { + "asInt": "1", + "attributes": [ + { + "key": "request", + "value": { + "stringValue": "head" + } + } + ], + "startTimeUnixNano": "1649969943717902800", + "timeUnixNano": "1649969943717902800" + }, + { + "asInt": "1", + "attributes": [ + { + "key": "request", + "value": { + "stringValue": "options" + } + } + ], + "startTimeUnixNano": "1649969943717902800", + "timeUnixNano": "1649969943717902800" + }, + { + "asInt": "1", + "attributes": [ + { + "key": "request", + "value": { + "stringValue": "post" + } + } + ], + "startTimeUnixNano": "1649969943717902800", + "timeUnixNano": "1649969943717902800" + }, + { + "asInt": "1", + "attributes": [ + { + "key": "request", + "value": { + "stringValue": "put" + } + } + ], + "startTimeUnixNano": "1649969943717902800", + "timeUnixNano": "1649969943717902800" + }, + { + "asInt": "1", + "attributes": [ + { + "key": "request", + "value": { + "stringValue": "trace" + } + } + ], + "startTimeUnixNano": "1649969943717902800", + "timeUnixNano": "1649969943717902800" } ], "isMonotonic": true