registry/internal/api/server.go
pree-dew d237fc90f8
Add OpenTelemetry metrics instrumentation (#290)
## Motivation and Context
- It is important to have basic observability in place so that
availability issues can be figured out easily

## How Has This Been Tested?
- Registration of metrics is tested
- Prometheus endpoint `/metrics` is included in test cases to test the
metrics exposed
- Test locally to understand any regression.

## Breaking Changes
- No

## Types of changes
<!-- What types of changes does your code introduce? Put an `x` in all
the boxes that apply: -->
- [ ] Bug fix (non-breaking change which fixes an issue)
- [x] New feature (non-breaking change which adds functionality)
- [ ] Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] Documentation update

## Checklist
<!-- Go over all the following points, and put an `x` in all the boxes
that apply. -->
- [x] I have read the [MCP
Documentation](https://modelcontextprotocol.io)
- [x] My code follows the repository's style guidelines
- [x] New and existing tests pass locally
- [x] I have added appropriate error handling
- [ ] I have added or updated documentation as needed

## Additional context
- Telemetry implementation is currently done by keeping metrics in mind
as of now, other types of telemetry can be added on top of it later.
- Instrumentation takes care of these problems already:
- Cardinality control by limiting latency buckets and not including
labels that grows with throughput.
  - Latency buckets are added as per SLA guidelines
  - Each metric prefixed with `mcp` to easily identify.
- Pulling mechanism is used since the idea is to scrape metrics via an
agent like vmagent, prometheus agent or otel-collector.
- Metrics follow standard approach of defining counters, histogram and
gauges as per opentelemetry guidelines.
2025-08-21 14:23:37 +01:00

55 lines
1.3 KiB
Go

package api
import (
"context"
"log"
"net/http"
"time"
"github.com/danielgtaylor/huma/v2"
"github.com/modelcontextprotocol/registry/internal/api/router"
"github.com/modelcontextprotocol/registry/internal/config"
"github.com/modelcontextprotocol/registry/internal/service"
"github.com/modelcontextprotocol/registry/internal/telemetry"
)
// Server represents the HTTP server
type Server struct {
config *config.Config
registry service.RegistryService
humaAPI huma.API
server *http.Server
}
// NewServer creates a new HTTP server
func NewServer(cfg *config.Config, registryService service.RegistryService, metrics *telemetry.Metrics) *Server {
// Create HTTP mux and Huma API
mux := http.NewServeMux()
api := router.NewHumaAPI(cfg, registryService, mux, metrics)
server := &Server{
config: cfg,
registry: registryService,
humaAPI: api,
server: &http.Server{
Addr: cfg.ServerAddress,
Handler: mux,
ReadHeaderTimeout: 10 * time.Second,
},
}
return server
}
// Start begins listening for incoming HTTP requests
func (s *Server) Start() error {
log.Printf("HTTP server starting on %s", s.config.ServerAddress)
return s.server.ListenAndServe()
}
// Shutdown gracefully shuts down the server
func (s *Server) Shutdown(ctx context.Context) error {
return s.server.Shutdown(ctx)
}