Files
Sankofa/crossplane-provider-proxmox/pkg/metrics/prometheus_client.go
defiQUG 9daf1fd378 Apply Composer changes: comprehensive API updates, migrations, middleware, and infrastructure improvements
- Add comprehensive database migrations (001-024) for schema evolution
- Enhance API schema with expanded type definitions and resolvers
- Add new middleware: audit logging, rate limiting, MFA enforcement, security, tenant auth
- Implement new services: AI optimization, billing, blockchain, compliance, marketplace
- Add adapter layer for cloud integrations (Cloudflare, Kubernetes, Proxmox, storage)
- Update Crossplane provider with enhanced VM management capabilities
- Add comprehensive test suite for API endpoints and services
- Update frontend components with improved GraphQL subscriptions and real-time updates
- Enhance security configurations and headers (CSP, CORS, etc.)
- Update documentation and configuration files
- Add new CI/CD workflows and validation scripts
- Implement design system improvements and UI enhancements
2025-12-12 18:01:35 -08:00

112 lines
2.5 KiB
Go

package metrics
import (
"context"
"encoding/json"
"fmt"
"io"
"net/http"
"net/url"
"time"
"github.com/pkg/errors"
)
// PrometheusAPIClient implements PrometheusClient using Prometheus HTTP API
type PrometheusAPIClient struct {
endpoint string
client *http.Client
}
// NewPrometheusAPIClient creates a new Prometheus API client
func NewPrometheusAPIClient(endpoint string) *PrometheusAPIClient {
return &PrometheusAPIClient{
endpoint: endpoint,
client: &http.Client{
Timeout: 30 * time.Second,
},
}
}
// QueryResponse represents a Prometheus query response
type QueryResponse struct {
Status string `json:"status"`
Data struct {
ResultType string `json:"resultType"`
Result []struct {
Metric map[string]string `json:"metric"`
Value []interface{} `json:"value"`
} `json:"result"`
} `json:"data"`
}
// Query executes a Prometheus query
func (c *PrometheusAPIClient) Query(ctx context.Context, query string) ([]MetricValue, error) {
// Build query URL
queryURL := fmt.Sprintf("%s/api/v1/query", c.endpoint)
params := url.Values{}
params.Set("query", query)
req, err := http.NewRequestWithContext(ctx, "GET", queryURL+"?"+params.Encode(), nil)
if err != nil {
return nil, errors.Wrap(err, "failed to create request")
}
resp, err := c.client.Do(req)
if err != nil {
return nil, errors.Wrap(err, "failed to execute request")
}
defer resp.Body.Close()
if resp.StatusCode != http.StatusOK {
body, _ := io.ReadAll(resp.Body)
return nil, fmt.Errorf("prometheus query failed: %d %s - %s", resp.StatusCode, resp.Status, string(body))
}
var queryResp QueryResponse
if err := json.NewDecoder(resp.Body).Decode(&queryResp); err != nil {
return nil, errors.Wrap(err, "failed to decode response")
}
if queryResp.Status != "success" {
return nil, fmt.Errorf("prometheus query returned error status: %s", queryResp.Status)
}
// Convert to MetricValue slice
var values []MetricValue
for _, result := range queryResp.Data.Result {
if len(result.Value) < 2 {
continue
}
// Parse timestamp (Unix timestamp in seconds)
timestampFloat, ok := result.Value[0].(float64)
if !ok {
continue
}
timestamp := time.Unix(int64(timestampFloat), 0)
// Parse value
var value float64
switch v := result.Value[1].(type) {
case string:
if _, err := fmt.Sscanf(v, "%f", &value); err != nil {
continue
}
case float64:
value = v
default:
continue
}
values = append(values, MetricValue{
Value: value,
Timestamp: timestamp,
Labels: result.Metric,
})
}
return values, nil
}