mirror of
https://github.com/hanzoai/o11y.git
synced 2026-10-15 12:58:33 +00:00
Re-apply the Hanzo-original packages that the wholesale SigNoz re-sync reverted,
reconciled against the new latest-SigNoz APIs. Build stays green (go build ./...
= 0, incl. -mod=readonly).
authz — Hanzo IAM is now the ONE AND ONLY authorization provider. OpenFGA is
ripped out entirely, not merely defaulted-away:
* Deleted pkg/authz/openfgaauthz, openfgaserver, openfgaschema, schema.go.
* Dropped github.com/openfga/* from go.mod/go.sum (go mod tidy).
* Removed the openfgav1 proto TupleKey from the authz.AuthZ interface and
authtypes; introduced a Hanzo-native authtypes.TupleKey / ReadRequestTupleKey
(a plain user/relation/object triple). This is what let openfga leave go.mod.
* New pkg/authz/iamauthz implements authz.AuthZ as the sole provider: the
decision path (Check*, BatchCheck, CheckTransactions) delegates to Hanzo IAM's
Casbin enforce endpoint over plain HTTP+JSON (/v1/iam/batch-enforce); tuple
storage (Write/Grant/Revoke/ReadTuples/ListObjects) maps onto IAM policies
(/v1/iam/{add,remove}-policy, get-policies). Role metadata stays in the local
SQL role store (not an IAM concern). Tuple (User,Relation,Object) → Casbin
(sub,obj,act) = (User,Object,Relation). Secrets (client id/secret) come from
env, never config.
* Wired as the sole factory in cmd/community/server.go; authz.Config default
provider = "iam". No provider-selection indirection remains.
zapreceiver + zapmetricreceiver — restored the luxfi/zap-native span/metric batch
receivers; API matches luxfi/zap v1.2.0 unchanged (promoted to a direct dep).
Tests pass.
billing + billingtypes — restored both standalone packages (types + noop Handler
contract). Their old route wiring lived in pkg/apiserver/o11yapiserver, which the
re-sync replaced with signozapiserver; recreating that provider is out of scope,
so billing is available-but-unwired pending an apiserver seam.
No ee/, no github.com/SigNoz/* imports, mount.go/NOTICE/LICENSE untouched.
141 lines
3.2 KiB
Go
141 lines
3.2 KiB
Go
// Copyright (C) 2025-2026, Lux Industries Inc. All rights reserved.
|
|
// SPDX-License-Identifier: BSD-3-Clause
|
|
|
|
package zapreceiver_test
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"net"
|
|
"sync"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/hanzoai/o11y/pkg/zapreceiver"
|
|
"github.com/luxfi/zap"
|
|
)
|
|
|
|
// TestReceiverIngestsZAPSpanBatch sends a hand-built SpanBatch envelope
|
|
// over ZAP and asserts the receiver's Handler is called with the same
|
|
// content. End-to-end smoke for the trace transport.
|
|
func TestReceiverIngestsZAPSpanBatch(t *testing.T) {
|
|
var (
|
|
mu sync.Mutex
|
|
got *zapreceiver.SpanBatch
|
|
done = make(chan struct{}, 1)
|
|
)
|
|
|
|
port := freePort(t)
|
|
rcv, err := zapreceiver.New(zapreceiver.Config{
|
|
Listen: fmt.Sprintf(":%d", port),
|
|
OnBatch: func(_ context.Context, b *zapreceiver.SpanBatch) error {
|
|
mu.Lock()
|
|
got = b
|
|
mu.Unlock()
|
|
select {
|
|
case done <- struct{}{}:
|
|
default:
|
|
}
|
|
return nil
|
|
},
|
|
})
|
|
if err != nil {
|
|
t.Fatalf("receiver: %v", err)
|
|
}
|
|
defer rcv.Stop()
|
|
|
|
// Build a synthetic SpanBatch + ZAP envelope by hand — no luxfi/trace
|
|
// dependency required for the test.
|
|
batch := zapreceiver.SpanBatch{
|
|
AppName: "test-service",
|
|
Version: "v0.1.0",
|
|
Resource: map[string]string{
|
|
"service.name": "test-service",
|
|
},
|
|
Spans: []zapreceiver.Span{
|
|
{
|
|
TraceID: "0102030405060708090a0b0c0d0e0f10",
|
|
SpanID: "1112131415161718",
|
|
Name: "test-span",
|
|
Kind: "internal",
|
|
StartUnixNs: 1700000000000000000,
|
|
EndUnixNs: 1700000000000001000,
|
|
},
|
|
},
|
|
}
|
|
payload, err := json.Marshal(&batch)
|
|
if err != nil {
|
|
t.Fatalf("marshal: %v", err)
|
|
}
|
|
|
|
b := zap.NewBuilder(128 + len(payload))
|
|
root := b.StartObject(16)
|
|
root.SetBytes(0, payload)
|
|
root.FinishAsRoot()
|
|
wire := b.FinishWithFlags(zapreceiver.MsgSpanBatch << 8)
|
|
|
|
// Client side: connect a one-shot ZAP node, send the envelope.
|
|
cli := zap.NewNode(zap.NodeConfig{
|
|
NodeID: "test-client",
|
|
ServiceType: "_o11y._tcp",
|
|
Port: 0,
|
|
NoDiscovery: true,
|
|
})
|
|
if err := cli.Start(); err != nil {
|
|
t.Fatalf("client start: %v", err)
|
|
}
|
|
defer cli.Stop()
|
|
|
|
if err := cli.ConnectDirect(fmt.Sprintf("127.0.0.1:%d", port)); err != nil {
|
|
t.Fatalf("connect: %v", err)
|
|
}
|
|
peers := cli.Peers()
|
|
if len(peers) == 0 {
|
|
t.Fatal("no peer after connect")
|
|
}
|
|
msg, err := zap.Parse(wire)
|
|
if err != nil {
|
|
t.Fatalf("parse outgoing: %v", err)
|
|
}
|
|
if err := cli.Send(context.Background(), peers[0], msg); err != nil {
|
|
t.Fatalf("send: %v", err)
|
|
}
|
|
|
|
select {
|
|
case <-done:
|
|
case <-time.After(3 * time.Second):
|
|
t.Fatal("timed out waiting for OnBatch")
|
|
}
|
|
|
|
mu.Lock()
|
|
defer mu.Unlock()
|
|
if got == nil {
|
|
t.Fatal("OnBatch never called")
|
|
}
|
|
if got.AppName != batch.AppName || got.Version != batch.Version {
|
|
t.Fatalf("metadata mismatch: got %+v want %+v", got, batch)
|
|
}
|
|
if len(got.Spans) != 1 || got.Spans[0].TraceID != batch.Spans[0].TraceID {
|
|
t.Fatalf("span mismatch: got %+v", got.Spans)
|
|
}
|
|
|
|
batches, dropped := rcv.Stats()
|
|
if batches != 1 || dropped != 0 {
|
|
t.Fatalf("stats: batches=%d dropped=%d", batches, dropped)
|
|
}
|
|
}
|
|
|
|
func freePort(t *testing.T) int {
|
|
t.Helper()
|
|
l, err := net.Listen("tcp", "127.0.0.1:0")
|
|
if err != nil {
|
|
t.Fatalf("listen: %v", err)
|
|
}
|
|
port := l.Addr().(*net.TCPAddr).Port
|
|
if err := l.Close(); err != nil {
|
|
t.Fatalf("close: %v", err)
|
|
}
|
|
return port
|
|
}
|