mirror of
https://github.com/lukaszraczylo/graphql-monitoring-proxy.git
synced 2026-06-15 02:47:52 +00:00
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 322a0b4929 | |||
| aab31c4bce | |||
| 68dd114da1 | |||
| 478a420b6b | |||
| d4dd3636f3 | |||
| fa24095b88 | |||
| 15d1dd7164 |
@@ -6,3 +6,9 @@ ARG TARGETOS
|
|||||||
COPY --chmod=777 --chown=nonroot:nonroot static/app /go/src/app
|
COPY --chmod=777 --chown=nonroot:nonroot static/app /go/src/app
|
||||||
ADD dist/bot-$TARGETOS-$TARGETARCH /go/src/app/graphql-proxy
|
ADD dist/bot-$TARGETOS-$TARGETARCH /go/src/app/graphql-proxy
|
||||||
ENTRYPOINT ["/go/src/app/graphql-proxy"]
|
ENTRYPOINT ["/go/src/app/graphql-proxy"]
|
||||||
|
|
||||||
|
LABEL org.opencontainers.image.maintainer="lukasz@raczylo.com" \
|
||||||
|
org.opencontainers.image.authors="lukasz@raczylo.com" \
|
||||||
|
org.opencontainers.image.title="graphql-monitoring-proxy" \
|
||||||
|
org.opencontainers.image.description="GraphQL monitoring proxy" \
|
||||||
|
org.opencontainers.image.url="https://github.com/lukaszraczylo/graphql-monitoring-proxy"
|
||||||
@@ -351,3 +351,5 @@ graphql_proxy_cache_hit{microservice="graphql_proxy",pod="hasura-w-proxy-interna
|
|||||||
graphql_proxy_cache_hit{pod="hasura-w-proxy-internal-6b5f4b4bbb-9xwfc",microservice="graphql_proxy"} 1
|
graphql_proxy_cache_hit{pod="hasura-w-proxy-internal-6b5f4b4bbb-9xwfc",microservice="graphql_proxy"} 1
|
||||||
graphql_proxy_cache_miss{microservice="graphql_proxy",pod="hasura-w-proxy-internal-6b5f4b4bbb-9xwfc"} 23
|
graphql_proxy_cache_miss{microservice="graphql_proxy",pod="hasura-w-proxy-internal-6b5f4b4bbb-9xwfc"} 23
|
||||||
```
|
```
|
||||||
|
|
||||||
|
.
|
||||||
+7
-15
@@ -282,23 +282,15 @@ func (suite *Tests) Test_parseGraphQLQuery() {
|
|||||||
suite.Run(tt.name, func() {
|
suite.Run(tt.name, func() {
|
||||||
cfg = &config{}
|
cfg = &config{}
|
||||||
parseConfig()
|
parseConfig()
|
||||||
ctx_headers := func() *fasthttp.RequestHeader {
|
ctx := suite.app.AcquireCtx(&fasthttp.RequestCtx{})
|
||||||
h := fasthttp.RequestHeader{}
|
|
||||||
for k, v := range tt.suppliedQuery.headers {
|
// Set headers
|
||||||
h.Add(k, v)
|
for k, v := range tt.suppliedQuery.headers {
|
||||||
}
|
ctx.Request().Header.Add(k, v)
|
||||||
return &h
|
|
||||||
}()
|
|
||||||
|
|
||||||
ctx_request := fasthttp.Request{
|
|
||||||
Header: *ctx_headers,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx_request.AppendBody([]byte(tt.suppliedQuery.body))
|
// Set body
|
||||||
|
ctx.Request().AppendBody([]byte(tt.suppliedQuery.body))
|
||||||
ctx := suite.app.AcquireCtx(&fasthttp.RequestCtx{
|
|
||||||
Request: ctx_request,
|
|
||||||
})
|
|
||||||
|
|
||||||
// defer func() {
|
// defer func() {
|
||||||
// cfg = &config{}
|
// cfg = &config{}
|
||||||
|
|||||||
@@ -55,9 +55,9 @@ func Benchmark_NewLogger(b *testing.B) {
|
|||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
b.Run(tt.name, func(b *testing.B) {
|
b.Run(tt.name, func(b *testing.B) {
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
got := New()
|
logger := New()
|
||||||
if tt.triggers.ModLevel.Level != 0 {
|
if tt.triggers.ModLevel.Level != 0 {
|
||||||
got = got.SetMinLogLevel(tt.triggers.ModLevel.Level)
|
logger.SetMinLogLevel(tt.triggers.ModLevel.Level)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package libpack_logger
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
|
||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
@@ -11,30 +10,6 @@ import (
|
|||||||
"github.com/goccy/go-json"
|
"github.com/goccy/go-json"
|
||||||
)
|
)
|
||||||
|
|
||||||
func captureStderr(f func()) string {
|
|
||||||
originalStderr := os.Stderr
|
|
||||||
r, w, _ := os.Pipe()
|
|
||||||
os.Stderr = w
|
|
||||||
f()
|
|
||||||
w.Close()
|
|
||||||
var buf bytes.Buffer
|
|
||||||
buf.ReadFrom(r)
|
|
||||||
os.Stderr = originalStderr
|
|
||||||
return buf.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
func captureStdOut(f func()) string {
|
|
||||||
originalStdout := os.Stdout
|
|
||||||
r, w, _ := os.Pipe()
|
|
||||||
os.Stdout = w
|
|
||||||
f()
|
|
||||||
w.Close()
|
|
||||||
var buf bytes.Buffer
|
|
||||||
buf.ReadFrom(r)
|
|
||||||
os.Stdout = originalStdout
|
|
||||||
return buf.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (suite *LoggerTestSuite) Test_LogMessageString() {
|
func (suite *LoggerTestSuite) Test_LogMessageString() {
|
||||||
msg := &LogMessage{
|
msg := &LogMessage{
|
||||||
Message: "test message",
|
Message: "test message",
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ var sortedLabelKeysCache = struct {
|
|||||||
}{}
|
}{}
|
||||||
|
|
||||||
func (ms *MetricsSetup) get_metrics_name(name string, labels map[string]string) string {
|
func (ms *MetricsSetup) get_metrics_name(name string, labels map[string]string) string {
|
||||||
const unknownPodName = "unknown"
|
|
||||||
var buf bytes.Buffer
|
var buf bytes.Buffer
|
||||||
|
|
||||||
podName := getPodName()
|
podName := getPodName()
|
||||||
|
|||||||
@@ -40,10 +40,9 @@ func createFasthttpClient(timeout int) *fasthttp.Client {
|
|||||||
|
|
||||||
// proxyTheRequest handles the request proxying logic.
|
// proxyTheRequest handles the request proxying logic.
|
||||||
func proxyTheRequest(c *fiber.Ctx, currentEndpoint string) error {
|
func proxyTheRequest(c *fiber.Ctx, currentEndpoint string) error {
|
||||||
var span trace.Span
|
|
||||||
ctx := context.Background()
|
|
||||||
|
|
||||||
if cfg.Tracing.Enable && tracer != nil {
|
if cfg.Tracing.Enable && tracer != nil {
|
||||||
|
var span trace.Span
|
||||||
|
spanCtx := context.Background()
|
||||||
// Extract trace information from header
|
// Extract trace information from header
|
||||||
if traceHeader := c.Get("X-Trace-Span"); traceHeader != "" {
|
if traceHeader := c.Get("X-Trace-Span"); traceHeader != "" {
|
||||||
spanInfo, err := libpack_tracing.ParseTraceHeader(traceHeader)
|
spanInfo, err := libpack_tracing.ParseTraceHeader(traceHeader)
|
||||||
@@ -53,14 +52,14 @@ func proxyTheRequest(c *fiber.Ctx, currentEndpoint string) error {
|
|||||||
Pairs: map[string]interface{}{"error": err.Error()},
|
Pairs: map[string]interface{}{"error": err.Error()},
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
if spanCtx, err := tracer.ExtractSpanContext(spanInfo); err == nil {
|
if extractedSpanCtx, err := tracer.ExtractSpanContext(spanInfo); err == nil {
|
||||||
ctx = trace.ContextWithSpanContext(ctx, spanCtx)
|
spanCtx = trace.ContextWithSpanContext(spanCtx, extractedSpanCtx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start a new span
|
// Start a new span
|
||||||
span, ctx = tracer.StartSpan(ctx, "proxy_request")
|
span, _ = tracer.StartSpan(spanCtx, "proxy_request")
|
||||||
defer span.End()
|
defer span.End()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+10
-16
@@ -87,23 +87,17 @@ func (suite *Tests) Test_proxyTheRequest() {
|
|||||||
cfg.Server.HostGraphQLReadOnly = tt.hostRO
|
cfg.Server.HostGraphQLReadOnly = tt.hostRO
|
||||||
}
|
}
|
||||||
|
|
||||||
ctx_headers := func() *fasthttp.RequestHeader {
|
ctx := suite.app.AcquireCtx(&fasthttp.RequestCtx{})
|
||||||
h := fasthttp.RequestHeader{}
|
|
||||||
for k, v := range tt.headers {
|
// Set headers
|
||||||
h.Add(k, v)
|
for k, v := range tt.headers {
|
||||||
}
|
ctx.Request().Header.Add(k, v)
|
||||||
return &h
|
|
||||||
}()
|
|
||||||
|
|
||||||
ctx_request := fasthttp.Request{
|
|
||||||
Header: *ctx_headers,
|
|
||||||
}
|
}
|
||||||
ctx_request.SetBody([]byte(tt.body))
|
|
||||||
ctx_request.SetRequestURI(tt.path)
|
// Set body and other request properties
|
||||||
ctx_request.Header.SetMethod("POST")
|
ctx.Request().SetBody([]byte(tt.body))
|
||||||
ctx := suite.app.AcquireCtx(&fasthttp.RequestCtx{
|
ctx.Request().SetRequestURI(tt.path)
|
||||||
Request: ctx_request,
|
ctx.Request().Header.SetMethod("POST")
|
||||||
})
|
|
||||||
res := parseGraphQLQuery(ctx)
|
res := parseGraphQLQuery(ctx)
|
||||||
assert.NotNil(ctx, "Fiber context is nil", tt.name)
|
assert.NotNil(ctx, "Fiber context is nil", tt.name)
|
||||||
err := proxyTheRequest(ctx, res.activeEndpoint)
|
err := proxyTheRequest(ctx, res.activeEndpoint)
|
||||||
|
|||||||
+5
-13
@@ -12,8 +12,6 @@ import (
|
|||||||
sdktrace "go.opentelemetry.io/otel/sdk/trace"
|
sdktrace "go.opentelemetry.io/otel/sdk/trace"
|
||||||
semconv "go.opentelemetry.io/otel/semconv/v1.21.0"
|
semconv "go.opentelemetry.io/otel/semconv/v1.21.0"
|
||||||
"go.opentelemetry.io/otel/trace"
|
"go.opentelemetry.io/otel/trace"
|
||||||
"google.golang.org/grpc"
|
|
||||||
"google.golang.org/grpc/credentials/insecure"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type TracingSetup struct {
|
type TracingSetup struct {
|
||||||
@@ -27,23 +25,17 @@ type TraceSpanInfo struct {
|
|||||||
|
|
||||||
// NewTracing creates a new tracing setup with OTLP exporter
|
// NewTracing creates a new tracing setup with OTLP exporter
|
||||||
func NewTracing(ctx context.Context, endpoint string) (*TracingSetup, error) {
|
func NewTracing(ctx context.Context, endpoint string) (*TracingSetup, error) {
|
||||||
if ctx == nil {
|
if ctx.Err() != nil {
|
||||||
return nil, fmt.Errorf("context cannot be nil")
|
return nil, fmt.Errorf("invalid context: %v", ctx.Err())
|
||||||
}
|
}
|
||||||
if endpoint == "" {
|
if endpoint == "" {
|
||||||
return nil, fmt.Errorf("endpoint cannot be empty")
|
return nil, fmt.Errorf("endpoint cannot be empty")
|
||||||
}
|
}
|
||||||
|
|
||||||
conn, err := grpc.DialContext(ctx, endpoint,
|
exporter, err := otlptracegrpc.New(ctx,
|
||||||
grpc.WithTransportCredentials(insecure.NewCredentials()),
|
otlptracegrpc.WithEndpoint(endpoint),
|
||||||
grpc.WithBlock(),
|
otlptracegrpc.WithInsecure(),
|
||||||
grpc.WithReturnConnectionError(),
|
|
||||||
)
|
)
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("failed to create gRPC connection to collector: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
exporter, err := otlptracegrpc.New(ctx, otlptracegrpc.WithGRPCConn(conn))
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to create trace exporter: %w", err)
|
return nil, fmt.Errorf("failed to create trace exporter: %w", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,10 +65,11 @@ func TestNewTracing(t *testing.T) {
|
|||||||
assert.Contains(t, err.Error(), "endpoint cannot be empty")
|
assert.Contains(t, err.Error(), "endpoint cannot be empty")
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("nil context", func(t *testing.T) {
|
t.Run("invalid context", func(t *testing.T) {
|
||||||
_, err := NewTracing(nil, "localhost:4317")
|
ctx, cancel := context.WithCancel(context.Background())
|
||||||
assert.Error(t, err, "Expected error for nil context")
|
cancel() // Cancel the context immediately
|
||||||
assert.Contains(t, err.Error(), "context cannot be nil")
|
_, err := NewTracing(ctx, "localhost:4317")
|
||||||
|
assert.Error(t, err, "Expected error for invalid context")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user