Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions openapi/Swarm.yaml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
openapi: 3.0.3

info:
version: 8.1.1
version: 8.1.2
title: Bee API
description: "API endpoints for interacting with the Swarm network, supporting file operations, messaging, and node management"

Expand Down Expand Up @@ -1114,7 +1114,7 @@ paths:
schema:
$ref: "SwarmCommon.yaml#/components/schemas/FeedType"
required: false
description: "Feed indexing scheme (default: sequence)"
description: "Feed indexing scheme. Only sequence is supported; other values are ignored and sequence is always used."
- $ref: "SwarmCommon.yaml#/components/parameters/SwarmPinParameter"
- $ref: "SwarmCommon.yaml#/components/parameters/SwarmPostageBatchId"
- $ref: "SwarmCommon.yaml#/components/parameters/SwarmAct"
Expand Down Expand Up @@ -1179,7 +1179,7 @@ paths:
schema:
$ref: "SwarmCommon.yaml#/components/schemas/FeedType"
required: false
description: "Feed indexing scheme (default: sequence)"
description: "Feed indexing scheme. Only sequence is supported; other values are ignored and sequence is always used."
- $ref: "SwarmCommon.yaml#/components/parameters/SwarmOnlyRootChunkParameter"
- $ref: "SwarmCommon.yaml#/components/parameters/SwarmCache"
- $ref: "SwarmCommon.yaml#/components/parameters/SwarmRedundancyStrategyParameter"
Expand Down
4 changes: 3 additions & 1 deletion openapi/SwarmCommon.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -866,7 +866,9 @@ components:

FeedType:
type: string
pattern: "^(sequence|epoch)$"
description: Feed indexing scheme. Only sequence is supported by the HTTP API.
enum:
- sequence

IsRetrievableResponse:
type: object
Expand Down
56 changes: 52 additions & 4 deletions pkg/feeds/factory/factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,27 +5,75 @@
package factory

import (
"context"
"errors"
"strings"
"time"

"github.com/ethersphere/bee/v2/pkg/feeds"
"github.com/ethersphere/bee/v2/pkg/feeds/epochs"
"github.com/ethersphere/bee/v2/pkg/feeds/sequence"
storage "github.com/ethersphere/bee/v2/pkg/storage"
"github.com/ethersphere/bee/v2/pkg/swarm"
)

type factory struct {
storage.Getter
metrics metrics
}

func New(getter storage.Getter) feeds.Factory {
return &factory{getter}
return &factory{
Getter: getter,
metrics: newMetrics(),
}
}

func (f *factory) NewLookup(t feeds.Type, feed *feeds.Feed) (feeds.Lookup, error) {
var lookup feeds.Lookup
switch t {
case feeds.Sequence:
return sequence.NewAsyncFinder(f.Getter, feed), nil
lookup = sequence.NewAsyncFinder(f.Getter, feed)
case feeds.Epoch:
return epochs.NewAsyncFinder(f.Getter, feed), nil
lookup = epochs.NewAsyncFinder(f.Getter, feed)
default:
return nil, feeds.ErrFeedTypeNotFound
}

return f.wrapLookup(t, lookup), nil
}

func (f *factory) wrapLookup(t feeds.Type, lookup feeds.Lookup) feeds.Lookup {
return &instrumentedLookup{
lookup: lookup,
typ: strings.ToLower(t.String()),
m: f.metrics,
}
}

type instrumentedLookup struct {
lookup feeds.Lookup
typ string
m metrics
}

return nil, feeds.ErrFeedTypeNotFound
func (l *instrumentedLookup) At(ctx context.Context, at int64, after uint64) (swarm.Chunk, feeds.Index, feeds.Index, error) {
l.m.LookupStarted.WithLabelValues(l.typ).Inc()
start := time.Now()
ch, cur, next, err := l.lookup.At(ctx, at, after)
l.m.LookupDuration.WithLabelValues(l.typ, lookupResult(ch, err)).Observe(time.Since(start).Seconds())
return ch, cur, next, err
}

func lookupResult(ch swarm.Chunk, err error) string {
switch {
case err != nil && errors.Is(err, context.Canceled):
return "canceled"
case err != nil:
return "error"
case ch == nil:
return "not_found"
default:
return "found"
}
}
49 changes: 49 additions & 0 deletions pkg/feeds/factory/metrics.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Copyright 2026 The Swarm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package factory

import (
"github.com/prometheus/client_golang/prometheus"

m "github.com/ethersphere/bee/v2/pkg/metrics"
)

type metrics struct {
// all metrics fields must be exported
// to be able to return them by Metrics()
// using reflection
LookupStarted *prometheus.CounterVec
LookupDuration *prometheus.HistogramVec
}

func newMetrics() metrics {
subsystem := "feeds"

return metrics{
LookupStarted: prometheus.NewCounterVec(
prometheus.CounterOpts{
Namespace: m.Namespace,
Subsystem: subsystem,
Name: "lookup_started_total",
Help: "Number of feed lookup attempts started.",
},
[]string{"type"},
),
LookupDuration: prometheus.NewHistogramVec(
prometheus.HistogramOpts{
Namespace: m.Namespace,
Subsystem: subsystem,
Name: "lookup_duration_seconds",
Help: "Histogram of feed lookup durations.",
Buckets: []float64{0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1, 2.5, 5, 10},
},
[]string{"type", "result"},
),
}
}

func (f *factory) Metrics() []prometheus.Collector {
return m.PrometheusCollectorsFromFields(f.metrics)
}
3 changes: 3 additions & 0 deletions pkg/node/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -1414,6 +1414,9 @@ func NewBee(
apiService.MustRegisterMetrics(retrieval.Metrics()...)
apiService.MustRegisterMetrics(lightNodes.Metrics()...)
apiService.MustRegisterMetrics(hive.Metrics()...)
if feedFactoryMetrics, ok := feedFactory.(metrics.Collector); ok {
apiService.MustRegisterMetrics(feedFactoryMetrics.Metrics()...)
}

if bs, ok := batchStore.(metrics.Collector); ok {
apiService.MustRegisterMetrics(bs.Metrics()...)
Expand Down
Loading