Skip to content

Commit

Permalink
Move From Opentracing To OpenTelemetry
Browse files Browse the repository at this point in the history
Signed-off-by: rodneyosodo <[email protected]>
  • Loading branch information
rodneyosodo committed Jul 25, 2023
1 parent 0d3630a commit e1e53d1
Show file tree
Hide file tree
Showing 10 changed files with 204 additions and 6 deletions.
4 changes: 1 addition & 3 deletions agent/api/grpc/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,7 @@ import (
"google.golang.org/grpc"
)

const (
svcName = "agent_proto.AgentService"
)
const svcName = "agent_proto.AgentService"

type grpcClient struct {
run endpoint.Endpoint
Expand Down
1 change: 0 additions & 1 deletion cmd/agent/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,6 @@ func main() {
g.Go(func() error {
return hs.Start()
})

g.Go(func() error {
return gs.Start()
})
Expand Down
2 changes: 1 addition & 1 deletion cmd/cli/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ func main() {

logger, err := logger.New(os.Stdout, cfg.LogLevel)
if err != nil {
log.Fatalf("Error creating logger: %s", err)
log.Fatalf(err.Error())
}

agentGRPCConfig := grpc.Config{}
Expand Down
6 changes: 6 additions & 0 deletions internal/clients/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// Copyright (c) Mainflux
// SPDX-License-Identifier: Apache-2.0

// Package clients contains the domain concept definitions needed to support
// Mainflux clients functionality for example: postgres, redis, grpc, jaeger.
package clients
6 changes: 6 additions & 0 deletions internal/clients/jaeger/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// Copyright (c) Mainflux
// SPDX-License-Identifier: Apache-2.0

// Package jaeger contains the domain concept definitions needed to support
// Mainflux Jaeger functionality.
package jaeger
62 changes: 62 additions & 0 deletions internal/clients/jaeger/provider.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// Copyright (c) Mainflux
// SPDX-License-Identifier: Apache-2.0

package jaeger

import (
"context"
"errors"

jaegerp "go.opentelemetry.io/contrib/propagators/jaeger"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/exporters/jaeger"
"go.opentelemetry.io/otel/sdk/resource"
tracesdk "go.opentelemetry.io/otel/sdk/trace"
semconv "go.opentelemetry.io/otel/semconv/v1.12.0"
)

var (
errNoURL = errors.New("URL is empty")
errNoSvcName = errors.New("Service Name is empty")
)

// NewProvider initializes Jaeger TraceProvider.
func NewProvider(svcName, url, instanceID string) (*tracesdk.TracerProvider, error) {
if url == "" {
return nil, errNoURL
}

if svcName == "" {
return nil, errNoSvcName
}

exporter, err := jaeger.New(jaeger.WithCollectorEndpoint(jaeger.WithEndpoint(url)))
if err != nil {
return nil, err
}

attributes := []attribute.KeyValue{
semconv.ServiceNameKey.String(svcName),
attribute.String("InstanceID", instanceID),
}

hostAttr, err := resource.New(context.TODO(), resource.WithHost(), resource.WithOSDescription(), resource.WithContainer())
if err != nil {
return nil, err
}
attributes = append(attributes, hostAttr.Attributes()...)

tp := tracesdk.NewTracerProvider(
tracesdk.WithSampler(tracesdk.AlwaysSample()),
tracesdk.WithBatcher(exporter),
tracesdk.WithResource(resource.NewWithAttributes(
semconv.SchemaURL,
attributes...,
)),
)
otel.SetTracerProvider(tp)
otel.SetTextMapPropagator(jaegerp.Jaeger{})

return tp, nil
}
1 change: 0 additions & 1 deletion internal/server/grpc/grpc.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,6 @@ func (s *Server) Start() error {
return s.Stop()
case err := <-errCh:
s.Cancel()

return err
}
}
Expand Down
27 changes: 27 additions & 0 deletions pkg/grpc/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package grpc

import (
"github.com/mainflux/mainflux/pkg/errors"
agentapi "github.com/ultravioletrs/agent/agent/api/grpc"
"github.com/ultravioletrs/agent/internal/env"
)

const envAgentGRPCPrefix = "AGENT_GRPC_"

var errGrpcConfig = errors.New("failed to load grpc configuration")

// Setup loads Users gRPC configuration from environment variable and creates new Users gRPC API.
func Setup() (*Client, error) {
config := Config{}
if err := env.Parse(&config, env.Options{Prefix: envAgentGRPCPrefix}); err != nil {
return nil, errors.Wrap(errGrpcConfig, err)
}

conn, secure, err := connect(config)
if err != nil {
return nil, err
}
client := agentapi.NewClient(conn, config.Timeout)

return setup(conn, secure, client)
}
95 changes: 95 additions & 0 deletions pkg/grpc/connect.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package grpc

import (
"time"

"github.com/mainflux/mainflux/pkg/errors"
"github.com/ultravioletrs/agent/agent"
"go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
gogrpc "google.golang.org/grpc"
"google.golang.org/grpc/credentials"
"google.golang.org/grpc/credentials/insecure"
)

var (
errGrpcConnect = errors.New("failed to connect to grpc server")
errGrpcClose = errors.New("failed to close grpc connection")
)

type Config struct {
ClientTLS bool `env:"CLIENT_TLS" envDefault:"false"`
CACerts string `env:"CA_CERTS" envDefault:""`
URL string `env:"URL" envDefault:""`
Timeout time.Duration `env:"TIMEOUT" envDefault:"1s"`
}

type ClientHandler interface {
Close() error
IsSecure() bool
Secure() string
}

type Client struct {
*gogrpc.ClientConn
agent.AgentServiceClient
secure bool
}

var _ ClientHandler = (*Client)(nil)

// connect creates new gRPC client and connect to gRPC server.
func connect(cfg Config) (*gogrpc.ClientConn, bool, error) {
var opts []gogrpc.DialOption
secure := false
tc := insecure.NewCredentials()

if cfg.ClientTLS && cfg.CACerts != "" {
var err error
tc, err = credentials.NewClientTLSFromFile(cfg.CACerts, "")
if err != nil {
return nil, secure, err
}
secure = true
}

opts = append(opts, gogrpc.WithTransportCredentials(tc), gogrpc.WithUnaryInterceptor(otelgrpc.UnaryClientInterceptor()))

conn, err := gogrpc.Dial(cfg.URL, opts...)
if err != nil {
return nil, secure, errors.Wrap(errGrpcConnect, err)
}

return conn, secure, nil
}

// setup creates new gRPC client.
func setup(conn *gogrpc.ClientConn, secure bool, agent agent.AgentServiceClient) (*Client, error) {
return &Client{
ClientConn: conn,
AgentServiceClient: agent,
secure: secure,
}, nil
}

// Close shuts down the gRPC connection.
func (c *Client) Close() error {
if err := c.ClientConn.Close(); err != nil {
return errors.Wrap(errGrpcClose, err)
}

return nil
}

// IsSecure is utility method for checking if
// the client is running with TLS enabled.
func (c *Client) IsSecure() bool {
return c.secure
}

// Secure is used for pretty printing TLS info.
func (c *Client) Secure() string {
if c.secure {
return "with TLS"
}
return "without TLS"
}
6 changes: 6 additions & 0 deletions pkg/grpc/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// Copyright (c) Mainflux
// SPDX-License-Identifier: Apache-2.0

// Package grpc contains the domain concept definitions needed to support
// Mainflux grpc functionality.
package grpc

0 comments on commit e1e53d1

Please sign in to comment.