Add REST API to OpAMP Server Example#497
Add REST API to OpAMP Server Example#497juandemanjon wants to merge 15 commits intoopen-telemetry:mainfrom
Conversation
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## main #497 +/- ##
=======================================
Coverage 81.67% 81.67%
=======================================
Files 27 27
Lines 2134 2134
=======================================
Hits 1743 1743
Misses 266 266
Partials 125 125 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
michel-laterman
left a comment
There was a problem hiding this comment.
I'm worried that redefining the OpAMP spec directly as an OpenAPI spec here will lead to extra work when demoing features for the example server.
internal/examples/makefile
Outdated
| # Test targets | ||
| .PHONY: test | ||
| test: | ||
| $(GOCMD) test -v -p 1 ./... |
There was a problem hiding this comment.
Please add the -race flag
internal/examples/docker-compose.yml
Outdated
| deploy: | ||
| replicas: 1 | ||
|
|
||
| opamp-ui: |
There was a problem hiding this comment.
Why do we need another UI server?
I really don't think the example compose should have these extra services.
Currently the examples dir only shows off the opamp-go library, introducing something like the otel/opentelemetry-collector-contrib image now introduces a demo for the opentelemetry-collector-contrib repo.
There was a problem hiding this comment.
You're right, this was a leftover I forgot to remove. I'm working on a new responsive UI in a separate issue, but it doesn't belong yet in the example compose. Removing it now.
I am going to keep the otel-collector service because the current server/agent example leverages it and I was trying to avoid these log messages. It is still working in progress
026/01/16 21:57:43.502169 [OPAMP] Connection settings for instance 019bca87de0f7afe84fdaeed99d9915d ConnectionSettingsStatuses_APPLYING (err=) hash=1d02a705cb821d9261f1b9b7f039ef1fe4a0431bc6c204060b7365e77eb3b569
2026/01/16 21:57:43.504191 [OPAMP] Connection settings for instance 019bca87de0f7afe84fdaeed99d9915d ConnectionSettingsStatuses_APPLIED (err=) hash=1d02a705cb821d9261f1b9b7f039ef1fe4a0431bc6c204060b7365e77eb3b569
2026/01/16 21:57:48 failed to upload metrics: Post "http://localhost:4318/v1/metrics": dial tcp 127.0.0.1:4318: connect: connection refused
2026/01/16 21:57:53 failed to upload metrics: Post "http://localhost:4318/v1/metrics": dial tcp 127.0.0.1:4318: connect: connection refused
2026/01/16 21:57:58 failed to upload metrics: Post "http://localhost:4318/v1/metrics": dial tcp 127.0.0.1:4318: connect: connection refused
2026/01/16 21:58:03 failed to upload metrics: Post "http://localhost:4318/v1/metrics": dial tcp 127.0.0.1:4318: connect: connection refused
| 1. Add handler method to `ApiServer` struct in `api.go` | ||
| 2. Register route in `Start()` method | ||
| 3. Add tests in `api_test.go` | ||
| 4. Update OpenAPI spec in `openapi.yaml` | ||
| 5. Update this README |
There was a problem hiding this comment.
What do you think about using a tool like oapi-codegen to generate code from the spec instead of having manual updates?
I find that it's really easy for the spec to drift from the implementation over time if it needs to be manually updated.
There was a problem hiding this comment.
This is a great integration idea after getting a working REST API
| ### Capabilities Bitmask | ||
|
|
||
| The `capabilities` field indicates what features the agent supports: | ||
|
|
||
| | Value | Capability | Description | | ||
| |--------|---------------------------------------|----------------------------------------------| | ||
| | 0x1 | ReportsStatus | Agent can report status | | ||
| | 0x2 | AcceptsRemoteConfig | Agent accepts remote configuration | | ||
| | 0x4 | ReportsEffectiveConfig | Agent reports its effective config | | ||
| | 0x8 | AcceptsRestartCommand | Agent can be restarted remotely | | ||
| | 0x10 | ReportsHealth | Agent reports health status | | ||
| | 0x20 | ReportsRemoteConfig | Agent reports remote config status | | ||
| | 0x40 | AcceptsOpAMPConnectionSettings | Agent accepts OpAMP connection settings | | ||
| | 0x80 | AcceptsOtherConnectionSettings | Agent accepts other connection settings | | ||
| | 0x100 | AcceptsPackages | Agent accepts package installations | | ||
| | 0x200 | ReportsPackageStatuses | Agent reports package statuses | | ||
| | 0x400 | ReportsOwnTraces | Agent reports its own traces | | ||
| | 0x800 | ReportsOwnMetrics | Agent reports its own metrics | | ||
| | 0x1000 | ReportsOwnLogs | Agent reports its own logs | | ||
| | 0x2000 | AcceptsOpAMPConnectionSettingsRequest | Agent accepts connection settings requests | | ||
| | 0x4000 | ReportsAvailableComponents | Agent reports available components | |
There was a problem hiding this comment.
I think we should just link to the opamp-spec here instead (also for other areas in the README that refer to things we have defined there).
| ## Future Enhancements | ||
|
|
||
| Potential additions to consider: | ||
|
|
||
| - Pagination for agent lists | ||
| - Filtering and searching agents | ||
| - WebSocket endpoint for real-time updates | ||
| - Agent restart command endpoint | ||
| - Package management endpoints | ||
| - Metrics and health endpoints | ||
| - Authentication and authorization |
There was a problem hiding this comment.
This seems like a feature set for a "real" server - is the goal to use examples/server in that manner?
There was a problem hiding this comment.
Many of these are specifically useful for UI/REST integration. Features like pagination, filtering, searching, and WebSocket updates are common requirements when building a web UI to visualize and manage agents. The REST API demonstrates how to expose OpAMP server functionality in a way that's consumable by frontends or other REST clients
| PackageStatus: | ||
| type: object | ||
| properties: | ||
| name: | ||
| type: string | ||
| version: | ||
| type: string | ||
| status: | ||
| type: string | ||
| enum: | ||
| - INSTALLED | ||
| - INSTALLING | ||
| - INSTALL_FAILED |
There was a problem hiding this comment.
Does not have the DOWNLOADING state: https://github.com/open-telemetry/opamp-spec/blob/8aa38f81e117df586b8f641b94cb93cc6137efa2/proto/opamp.proto#L974-L998
I'm a bit worried about redefining the spec here; If we add to the opamp-spec, will we now also need to ensure that the example server API here is synchronized? It seems like additional work.
Can we instead be less prescriptive for this API? For example, just use
PackageStatus:
type: object
description: "See https://github.com/open-telemetry/opamp-spec/blob/main/specification.md#agenttoserverpackage_statuses"
properties: {}Configure all services to use host networking. This allows the agent to connect to the hardcoded localhost:4318 collector endpoint without connection errors.
tigrannajaryan
left a comment
There was a problem hiding this comment.
@juandemanjon thank you for the effort but I am not sure this repository is the right place for such an extensive example.
This adds 1300 lines that needs to be maintained that are only tangentially related to OpAMP.
@open-telemetry/opamp-go-approvers anyone interested in personally taking ownership and maintaining this long term?
Blocking it for now.
|
I understand your concerns. I will be happy to maintain the API. I previously mentioned moving the examples out of opamp-go/internal. Maybe now is time to have opamp-go-contrib. Let's talk about it in the next sig |
|
This PR was marked stale. It will be closed in 30 days without additional activity. |
Add REST API to OpAMP Server Example
Fixes #474
Summary
This PR introduces a REST API for the OpAMP Server example, enabling clean separation between the UI layer and server logic. The API exposes programmatic access to connected agents, allowing modern web applications, CLI tools, and third-party clients to interact seamlessly with the OpAMP server.
Changes
New Package:
internal/examples/server/apisrvAdded a new
apisrvpackage that implements a REST API server running on port 4322.API Endpoints
GET /api/v1/agents
GET /api/v1/agents/{instanceid}
POST /api/v1/agents/{instanceid}/config
Features
Documentation
Testing
Integration
uisrv(no breaking changes)Architecture
Testing Instructions
Start the Server
Test the API
List all agents:
Get specific agent:
curl http://localhost:4322/api/v1/agents/{agent-uuid}Update agent config:
curl -X POST http://localhost:4322/api/v1/agents/{agent-uuid}/config \ -H "Content-Type: application/json" \ -d '{"config": "receivers:\n otlp:\n protocols:\n grpc:\n endpoint: 0.0.0.0:4317\n"}'Run Tests
Files Changed
internal/examples/server/apisrv/api.go- API server implementationinternal/examples/server/apisrv/api_test.go- Comprehensive test suiteinternal/examples/server/apisrv/README.md- API documentationinternal/examples/server/apisrv/openapi.yaml- OpenAPI specificationinternal/examples/server/main.go- Integration with main servergo.mod- Addedgithub.com/madflojo/testcertsas direct dependencyBreaking Changes
None. The API server runs alongside the existing UI server without any breaking changes.