Integrate BACKBEAT SDK and resolve KACHING license validation

Major integrations and fixes:
- Added BACKBEAT SDK integration for P2P operation timing
- Implemented beat-aware status tracking for distributed operations
- Added Docker secrets support for secure license management
- Resolved KACHING license validation via HTTPS/TLS
- Updated docker-compose configuration for clean stack deployment
- Disabled rollback policies to prevent deployment failures
- Added license credential storage (CHORUS-DEV-MULTI-001)

Technical improvements:
- BACKBEAT P2P operation tracking with phase management
- Enhanced configuration system with file-based secrets
- Improved error handling for license validation
- Clean separation of KACHING and CHORUS deployment stacks

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
anthonyrawlins
2025-09-06 07:56:26 +10:00
parent 543ab216f9
commit 9bdcbe0447
4730 changed files with 1480093 additions and 1916 deletions

View File

@@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2018 Protocol Labs
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@@ -0,0 +1,297 @@
// tracing provides high level method tracing for the [routing.Routing] API.
// Each method of the API has a corresponding method on [Tracer] which return either a defered wrapping callback or just defered callback.
package tracing
import (
"context"
"fmt"
"github.com/ipfs/go-cid"
"github.com/libp2p/go-libp2p/core/peer"
"github.com/libp2p/go-libp2p/core/routing"
"github.com/multiformats/go-multibase"
"github.com/multiformats/go-multihash"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/codes"
"go.opentelemetry.io/otel/trace"
)
// Tracer is the librairy name that will be passed to [otel.Tracer].
type Tracer string
func (t Tracer) StartSpan(ctx context.Context, name string, opts ...trace.SpanStartOption) (context.Context, trace.Span) {
return otel.Tracer(string(t)).Start(ctx, name, opts...)
}
const base = multibase.Base64url
func bytesAsMultibase(b []byte) string {
r, err := multibase.Encode(base, b)
if err != nil {
panic(fmt.Errorf("unreachable: %w", err))
}
return r
}
// keysAsMultibase avoids returning non utf8 which otel does not like.
func keysAsMultibase(name string, keys []multihash.Multihash) attribute.KeyValue {
keysStr := make([]string, len(keys))
for i, k := range keys {
keysStr[i] = bytesAsMultibase(k)
}
return attribute.StringSlice(name, keysStr)
}
func (t Tracer) Provide(routerName string, ctx context.Context, key cid.Cid, announce bool) (_ context.Context, end func(error)) {
// outline so the concatenation can be folded at compile-time
return t.provide(routerName+".Provide", ctx, key, announce)
}
func (t Tracer) provide(traceName string, ctx context.Context, key cid.Cid, announce bool) (_ context.Context, end func(error)) {
ctx, span := t.StartSpan(ctx, traceName)
if !span.IsRecording() {
span.End()
return ctx, func(error) {}
}
span.SetAttributes(
attribute.Stringer("key", key),
attribute.Bool("announce", announce),
)
return ctx, func(err error) {
if err != nil {
span.SetStatus(codes.Error, err.Error())
}
span.End()
}
}
func (t Tracer) ProvideMany(routerName string, ctx context.Context, keys []multihash.Multihash) (_ context.Context, end func(error)) {
// outline so the concatenation can be folded at compile-time
return t.provideMany(routerName+".ProvideMany", ctx, keys)
}
func (t Tracer) provideMany(traceName string, ctx context.Context, keys []multihash.Multihash) (_ context.Context, end func(error)) {
ctx, span := t.StartSpan(ctx, traceName)
if !span.IsRecording() {
span.End()
return ctx, func(error) {}
}
span.SetAttributes(keysAsMultibase("keys", keys))
return ctx, func(err error) {
if err != nil {
span.SetStatus(codes.Error, err.Error())
}
span.End()
}
}
func peerInfoToAttributes(p peer.AddrInfo) []attribute.KeyValue {
strs := make([]string, len(p.Addrs))
for i, v := range p.Addrs {
strs[i] = v.String()
}
return []attribute.KeyValue{
attribute.Stringer("id", p.ID),
attribute.StringSlice("addrs", strs),
}
}
func (t Tracer) FindProvidersAsync(routerName string, ctx context.Context, key cid.Cid, count int) (_ context.Context, passthrough func(<-chan peer.AddrInfo, error) <-chan peer.AddrInfo) {
// outline so the concatenation can be folded at compile-time
return t.findProvidersAsync(routerName+".FindProvidersAsync", ctx, key, count)
}
func (t Tracer) findProvidersAsync(traceName string, ctx context.Context, key cid.Cid, count int) (_ context.Context, passthrough func(<-chan peer.AddrInfo, error) <-chan peer.AddrInfo) {
ctx, span := t.StartSpan(ctx, traceName)
if !span.IsRecording() {
span.End()
return ctx, func(c <-chan peer.AddrInfo, _ error) <-chan peer.AddrInfo { return c }
}
span.SetAttributes(
attribute.Stringer("key", key),
attribute.Int("count", count),
)
return ctx, func(in <-chan peer.AddrInfo, err error) <-chan peer.AddrInfo {
if err != nil {
span.SetStatus(codes.Error, err.Error())
span.End()
return in
}
span.AddEvent("started streaming")
out := make(chan peer.AddrInfo)
go func() {
defer span.End()
defer close(out)
for v := range in {
span.AddEvent("found provider", trace.WithAttributes(peerInfoToAttributes(v)...))
select {
case out <- v:
case <-ctx.Done():
span.SetStatus(codes.Error, ctx.Err().Error())
}
}
}()
return out
}
}
func (t Tracer) FindPeer(routerName string, ctx context.Context, id peer.ID) (_ context.Context, end func(peer.AddrInfo, error)) {
// outline so the concatenation can be folded at compile-time
return t.findPeer(routerName+".FindPeer", ctx, id)
}
func (t Tracer) findPeer(traceName string, ctx context.Context, id peer.ID) (_ context.Context, end func(peer.AddrInfo, error)) {
ctx, span := t.StartSpan(ctx, traceName)
if !span.IsRecording() {
span.End()
return ctx, func(peer.AddrInfo, error) {}
}
span.SetAttributes(attribute.Stringer("key", id))
return ctx, func(p peer.AddrInfo, err error) {
defer span.End()
if err != nil {
span.SetStatus(codes.Error, err.Error())
return
}
span.AddEvent("found peer", trace.WithAttributes(peerInfoToAttributes(p)...))
}
}
func (t Tracer) PutValue(routerName string, ctx context.Context, key string, val []byte, opts ...routing.Option) (_ context.Context, end func(error)) {
// outline so the concatenation can be folded at compile-time
return t.putValue(routerName+".PutValue", ctx, key, val, opts...)
}
func (t Tracer) putValue(traceName string, ctx context.Context, key string, val []byte, opts ...routing.Option) (_ context.Context, end func(error)) {
ctx, span := t.StartSpan(ctx, traceName)
if !span.IsRecording() {
span.End()
return ctx, func(error) {}
}
span.SetAttributes(
attribute.String("key", bytesAsMultibase([]byte(key))),
attribute.String("value", bytesAsMultibase(val)),
attribute.Int("len(opts)", len(opts)),
)
return ctx, func(err error) {
if err != nil {
span.SetStatus(codes.Error, err.Error())
}
span.End()
}
}
func (t Tracer) GetValue(routerName string, ctx context.Context, key string, opts ...routing.Option) (_ context.Context, end func([]byte, error)) {
// outline so the concatenation can be folded at compile-time
return t.getValue(routerName+".GetValue", ctx, key, opts...)
}
func (t Tracer) getValue(traceName string, ctx context.Context, key string, opts ...routing.Option) (_ context.Context, end func([]byte, error)) {
ctx, span := t.StartSpan(ctx, traceName)
if !span.IsRecording() {
span.End()
return ctx, func([]byte, error) {}
}
span.SetAttributes(
attribute.String("key", bytesAsMultibase([]byte(key))),
attribute.Int("len(opts)", len(opts)),
)
return ctx, func(val []byte, err error) {
defer span.End()
if err != nil {
span.SetStatus(codes.Error, err.Error())
return
}
span.AddEvent("found value", trace.WithAttributes(
attribute.String("value", bytesAsMultibase(val))))
}
}
func (t Tracer) SearchValue(routerName string, ctx context.Context, key string, opts ...routing.Option) (_ context.Context, passthrough func(<-chan []byte, error) (<-chan []byte, error)) {
// outline so the concatenation can be folded at compile-time
return t.searchValue(routerName+".SearchValue", ctx, key, opts...)
}
func (t Tracer) searchValue(traceName string, ctx context.Context, key string, opts ...routing.Option) (_ context.Context, passthrough func(<-chan []byte, error) (<-chan []byte, error)) {
ctx, span := t.StartSpan(ctx, traceName)
if !span.IsRecording() {
span.End()
return ctx, func(c <-chan []byte, err error) (<-chan []byte, error) { return c, err }
}
span.SetAttributes(
attribute.String("key", bytesAsMultibase([]byte(key))),
attribute.Int("len(opts)", len(opts)),
)
return ctx, func(in <-chan []byte, err error) (<-chan []byte, error) {
if err != nil {
span.SetStatus(codes.Error, err.Error())
span.End()
return in, err
}
span.AddEvent("started streaming")
out := make(chan []byte)
go func() {
defer span.End()
defer close(out)
for v := range in {
span.AddEvent("found value", trace.WithAttributes(
attribute.String("value", bytesAsMultibase(v))),
)
select {
case out <- v:
case <-ctx.Done():
span.SetStatus(codes.Error, ctx.Err().Error())
}
}
}()
return out, nil
}
}
func (t Tracer) Bootstrap(routerName string, ctx context.Context) (_ context.Context, end func(error)) {
// outline so the concatenation can be folded at compile-time
return t.bootstrap(routerName+".Bootstrap", ctx)
}
func (t Tracer) bootstrap(traceName string, ctx context.Context) (_ context.Context, end func(error)) {
ctx, span := t.StartSpan(ctx, traceName)
if !span.IsRecording() {
span.End()
return ctx, func(error) {}
}
return ctx, func(err error) {
if err != nil {
span.SetStatus(codes.Error, err.Error())
}
span.End()
}
}