I'm running a pod of open telemetry collector that is exposed to port 4318 (running node js demo working perfectly)
but running this basic code sample (which basically just running a simple program after initiating the Tracer and sending spans)
package main
import (
"context"
"fmt"
"log"
"os"
"os/signal"
"time"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp"
// "go.opentelemetry.io/otel/propagation"
"go.opentelemetry.io/otel/sdk/resource"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
semconv "go.opentelemetry.io/otel/semconv/v1.4.0"
)
func initProvider() func() {
ctx := context.Background()
_, err := resource.New(ctx,
resource.WithAttributes(
semconv.ServiceNameKey.String("test-service"),
),
)
handleErr(err, "failed to create resource")
traceExporter, err := otlptracehttp.New(ctx,
otlptracehttp.WithInsecure(),
otlptracehttp.WithEndpoint("localhost:4318"),
)
handleErr(err, "failed to create trace exporter")
bsp := sdktrace.NewBatchSpanProcessor(traceExporter)
tracerProvider := sdktrace.NewTracerProvider(
// sdktrace.WithSampler(sdktrace.AlwaysSample()),
// sdktrace.WithResource(res),
sdktrace.WithSpanProcessor(bsp),
)
otel.SetTracerProvider(tracerProvider)
// otel.SetTextMapPropagator(propagation.TraceContext{})
return func() {
handleErr(tracerProvider.Shutdown(ctx), "failed to shutdown TracerProvider")
}
}
func initialize() {
traceExp, err := otlptracehttp.New(
context.Background(),
otlptracehttp.WithEndpoint("127.0.0.1:8082"),
otlptracehttp.WithURLPath("v1/traces"),
otlptracehttp.WithInsecure(),
)
if err != nil {
fmt.Println(err)
}
bsp := sdktrace.NewBatchSpanProcessor(traceExp)
tracerProvider := sdktrace.NewTracerProvider(
sdktrace.WithSpanProcessor(bsp),
)
otel.SetTracerProvider(tracerProvider)
}
func main() {
log.Printf("Waiting for connection...")
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt)
defer cancel()
// shutdown := initProvider()
// defer shutdown()
initProvider()
tracer := otel.Tracer("demo-client-tracer")
ctx, span := tracer.Start(context.TODO(), "span-name")
defer span.End()
for i := 0; i < 10; i++ {
_, iSpan := tracer.Start(ctx, fmt.Sprintf("Sample-%d", i))
log.Printf("Doing really hard work (%d / 10)\n", i+1)
<-time.After(time.Second)
iSpan.End()
}
log.Printf("Done!")
}
func handleErr(err error, message string) {
if err != nil {
log.Fatalf("%s: %v", message, err)
}
}
and Im getting :
OTLP partial success: empty message (0 spans rejected)
and no traces is being sent...
any ideas?
what am I missing ?
Related
I want to open websocket server whenever i want to and close but server does not close after writing "exit" when i go back to my main() and i try to start again it fails saying "httpHandleFunc multiple registration '/' " how do i close websocket server permanently and go back to main and start server again like switch on/off.
Another issue i am facing is client side errors with Bad Handshake when using gorilla mux as a handler.
#Server-Side Code
https://go.dev/play/p/n_I4xzOomWz
package main
import (
"bufio"
"flag"
"fmt"
"net/http"
"os"
"strings"
"time"
"github.com/gorilla/mux"
"github.com/gorilla/websocket"
log "github.com/sirupsen/logrus"
)
const (
// Time allowed to write a message to the peer.
writeWait = 10 * time.Second
// Maximum message size allowed from peer.
maxMessageSize = 8192
// Time allowed to read the next pong message from the peer.
pongWait = 60 * time.Second
// Send pings to peer with this period. Must be less than pongWait.
pingPeriod = (pongWait * 9) / 10
// Time to wait before force close on connection.
closeGracePeriod = 2 * time.Second
)
var (
server http.Server
addr = "0.0.0.0:443"
upgrader = websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool {
return true
},
}
)
func ping(ws *websocket.Conn, done chan struct{}) {
ticker := time.NewTicker(pingPeriod)
defer ticker.Stop()
for {
select {
case <-ticker.C:
if err := ws.WriteControl(websocket.PingMessage, []byte{}, time.Now().Add(writeWait)); err != nil {
log.Println("ping:", err)
}
case <-done:
return
}
}
}
// write message
func pumpStdout(ws *websocket.Conn, done chan struct{}) {
defer func() {
}()
for {
text := ReadInput("User220 > ")
if text == "exit" {
break
}
ws.SetWriteDeadline(time.Now().Add(writeWait))
if err := ws.WriteMessage(websocket.TextMessage, []byte(text)); err != nil {
ws.Close()
log.Errorln(err)
break
}
}
close(done)
ws.SetWriteDeadline(time.Now().Add(writeWait))
ws.WriteMessage(websocket.CloseMessage, websocket.FormatCloseMessage(websocket.CloseNormalClosure, ""))
time.Sleep(closeGracePeriod)
ws.Close()
}
// receive message
func pumpStdin(ws *websocket.Conn, done chan struct{}) {
defer ws.Close()
ws.SetReadLimit(maxMessageSize)
ws.SetReadDeadline(time.Now().Add(pongWait))
ws.SetPongHandler(func(string) error { ws.SetReadDeadline(time.Now().Add(pongWait)); return nil })
ticker := time.NewTicker(time.Second)
defer ticker.Stop()
for {
select {
case <-done:
break
case <-ticker.C:
_, message, err := ws.ReadMessage()
if err != nil {
ws.CloseHandler()
err := ws.UnderlyingConn().Close()
fmt.Println(err)
main()
}
if len(message) > 0 {
fmt.Printf("\r\n%sUser220 > ", message)
}
}
}
}
func WebsocketHandle(w http.ResponseWriter, r *http.Request) {
c, err := upgrader.Upgrade(w, r, nil)
if err != nil {
log.Fatalln(err)
}
defer c.Close()
stdoutDone := make(chan struct{})
go pumpStdout(c, stdoutDone)
go ping(c, stdoutDone)
pumpStdin(c, stdoutDone)
}
func start_socket() {
flag.Parse()
log.Printf("listen at %s", addr)
// ----------------------
mux := mux.NewRouter()
mux.HandleFunc("/", WebsocketHandle)
//-----------------------
http.HandleFunc("/", WebsocketHandle)
server = http.Server{Addr: addr}
log.Fatalln(server.ListenAndServe())
}
func stop_server() {
err := server.Close()
if err != nil {
log.Fatalln(err)
}
}
func ReadInput(promt string) string {
fmt.Printf("\n%s", promt)
reader := bufio.NewReader(os.Stdin)
input, _ := reader.ReadString('\n')
return strings.TrimSpace(input)
}
func main() {
for {
read := ReadInput("Main : ")
switch read {
case "start":
start_socket()
case "stop":
stop_server()
default:
fmt.Println("Not Sure")
}
}
}
Client side i am just polling and writing back the same message right now.
#Client-Side Code
https://go.dev/play/p/y4nUkvMFYec
package main
import (
"fmt"
"net/url"
"github.com/gorilla/websocket"
log "github.com/sirupsen/logrus"
)
var addr = "localhost:443"
func main() {
dial := websocket.Dialer{}
u := url.URL{Scheme: "ws", Host: addr, Path: "/"}
log.Printf("connecting to %s", u.String())
c, _, err := dial.Dial(u.String(), nil)
if err != nil {
log.Fatalln(err)
}
defer c.Close()
for {
_, message, err := c.ReadMessage()
if err != nil {
log.Fatalln(err)
}
fmt.Println("Recevied : " + string(message))
err = c.WriteMessage(websocket.TextMessage, message)
if err != nil {
log.Fatalln(err)
}
}
}
I'm somewhat new to go and am reworking code that I found somewhere else to fit my needs. Because of that, I don't totally understand what is happening here, although I get the general idea.
I'm running a few websocket clients using go routines, but I'm getting an unexpected error that causes the program to crash. My program seems to close one too many threads (excuse me if this is the wrong terminology) when there is an error reading a message from the websocket (check the conn.ReadMessage() func in the readHandler func). Any ideas on how would I work around this issue? I would really appreciate anyone taking the time to look through it. Thanks in advance!
package main
import (
"context"
"fmt"
"os"
"time"
"os/signal"
"syscall"
"sync"
"net/url"
"github.com/gorilla/websocket"
"strconv"
"encoding/json"
"log"
"bytes"
"compress/gzip"
"io/ioutil"
)
// Structs
type Ping struct {
Ping int64 `json:"ping"`
}
type Pong struct {
Pong int64 `json:"pong"`
}
type SubParams struct {
Sub string `json:"sub"`
ID string `json:"id"`
}
func InitSub(subType string, pair string, i int) []byte {
var idInt string = "id" + strconv.Itoa(i)
subStr := "market." + pair + "." + subType
sub := &SubParams{
Sub: subStr,
ID: idInt,
}
out, err := json.MarshalIndent(sub, "", " ")
if err != nil {
log.Println(err);
}
//log.Println(string(out))
return out
}
// main func
func main() {
var server string = "api.huobi.pro"
pairs := []string{"btcusdt", "ethusdt", "ltcusdt"}
comms := make(chan os.Signal, 1)
signal.Notify(comms, os.Interrupt, syscall.SIGTERM)
ctx := context.Background()
ctx, cancel := context.WithCancel(ctx)
var wg sync.WaitGroup
for x, pair := range pairs {
wg.Add(1)
go control(server, "ws", pair, ctx, &wg, x+1)
}
<-comms
cancel()
wg.Wait()
}
func control(server string, path string, pair string, ctx context.Context, wg *sync.WaitGroup, i int) {
fmt.Printf("Started control for %s\n", server)
url := url.URL {
Scheme: "wss",
Host: server,
Path: path,
}
fmt.Println(url.String())
conn, _, err := websocket.DefaultDialer.Dial(url.String(), nil)
if err != nil {
panic(err)
}
subscribe(conn, pair, i)
defer conn.Close()
var localwg sync.WaitGroup
localwg.Add(1)
go readHandler(ctx, conn, &localwg, server)
<- ctx.Done()
localwg.Wait()
wg.Done()
return
}
func readHandler(ctx context.Context, conn *websocket.Conn, wg *sync.WaitGroup, server string) {
for {
select {
case <- ctx.Done():
wg.Done()
return
default:
_, p, err := conn.ReadMessage()
if err != nil {
wg.Done()
fmt.Println(err)
}
r, err := gzip.NewReader(bytes.NewReader(p))
if(err == nil) {
result, err := ioutil.ReadAll(r)
if(err != nil) {
fmt.Println(err)
}
d := string(result)
fmt.Println(d)
var ping Ping
json.Unmarshal([]byte(d), &ping)
if (ping.Ping > 0) {
str := Pong{Pong: ping.Ping}
msg, err := json.Marshal(str)
if (err == nil) {
fmt.Println(string(msg))
conn.WriteMessage(websocket.TextMessage, []byte(msg))
}
}
}
}
}
}
func subscribe(conn *websocket.Conn, pair string, id int) {
sub := string(InitSub("trade.detail", pair, id))
err := conn.WriteMessage(websocket.TextMessage, []byte(sub))
if err != nil {
panic(err)
}
}
Break out of the readHandler loop when the connection fails:
_, p, err := conn.ReadMessage()
if err != nil {
wg.Done()
fmt.Println(err)
return // <--- add this line
}
Without the return, the function spins in a tight loop reading errors until the panic.
Use defer wg.Done() at the beginning of the goroutine to ensure that Done is called exactly once.
func readHandler(ctx context.Context, conn *websocket.Conn, wg *sync.WaitGroup, server string) {
defer wg.Done()
for {
select {
case <-ctx.Done():
return
default:
_, p, err := conn.ReadMessage()
if err != nil {
fmt.Println(err)
return
}
...
Update the control function also.
Because the caller does not execute any code concurrently with readHander, there's no value in running readHandler is a goroutine. Remove all references to wait groups from readHandler and call the function directly: change go readHandler(ctx, conn, &localwg, server) to readHandler(ctx, conn, server).
There are more issues, but this should move you further along.
How can I subscribe to the event "incoming transaction successful". That is, I want to know that ether has come to my wallet. How to do it using subscription. I do not understand anything.
package main
import (
"context"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethclient"
"log"
)
func main() {
client, err := ethclient.Dial("wss://mainnet.infura.io/ws/v3/XXXXXXXXXXXXXXXX")
if err != nil {
log.Fatal(err)
}
accs := map[string]string{
"0x92321477416e93Ea452f16015e2F2a13B3BDe8B7":"12e2cc06fb999fa29306f10db6b366e61a4946b9527286a0c56640c94cebd950",
}
keys := make([]common.Address, 0, len(accs))
for k := range accs {
keys = append(keys, common.HexToAddress(k))
}
var ch = make(chan types.Log)
sub, err := client.SubscribeFilterLogs(context.Background(), ethereum.FilterQuery{
BlockHash: nil,
FromBlock: nil,
ToBlock: nil,
Addresses: keys,
Topics: nil,
}, ch)
if err != nil {
log.Fatal(err)
}
defer sub.Unsubscribe()
for l := range ch {
// ???
}
}
Help me please. Where i can find example?
enter image description here
I'm looking through infura.io's API documentation and I'm not finding that they have an endpoint for payouts. The image that you linked above is their UI option for email notifications and has nothing to do with the API. In order to subscribe to an action, it would have to be initiated on their end. You would have to provide them with a callback to execute when that action occurs. Your callback would do the alerting, but they would call it when the trigger (a payout) occurred. Do they have a place to enter webhooks? If so, this would be your subscription.
While this option may not be a subscription, a possible workaround would be for you to poll the getBalance endpoint and compare the result to the previous result, and if there is an increase, alert you.
My solution
sub, err := client.SubscribeNewHead(context.Background(), ch)
get block
b, err := client.BlockByNumber(context.Background(), l.Number)
check all transactions
for _, tx := range b.Transactions() {
msg, err := tx.AsMessage(types.NewEIP155Signer(tx.ChainId()))
}
in msg.To() address )))
actually go-ethereum already provided a demo in their test script:
import (
"context"
"log"
"os"
"os/signal"
"syscall"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/ethclient/gethclient"
"github.com/ethereum/go-ethereum/rpc"
)
const (
url = "https://mainnet.infura.io/v3/xxxxxxxx"
wss = "wss://eth-mainnet.alchemyapi.io/v2/xxxxxxxxxxx"
// wss = "wss://mainnet.infura.io/ws/v3/xxxxxxxx"
)
func watch() {
backend, err := ethclient.Dial(url)
if err != nil {
log.Printf("failed to dial: %v", err)
return
}
rpcCli, err := rpc.Dial(wss)
if err != nil {
log.Printf("failed to dial: %v", err)
return
}
gcli := gethclient.New(rpcCli)
txch := make(chan common.Hash, 100)
_, err = gcli.SubscribePendingTransactions(context.Background(), txch)
if err != nil {
log.Printf("failed to SubscribePendingTransactions: %v", err)
return
}
for {
select {
case txhash := <-txch:
tx, _, err := backend.TransactionByHash(context.Background(), txhash)
if err != nil {
continue
}
data, _ := tx.MarshalJSON()
log.Printf("tx: %v", string(data))
}
}
}
func DoTest() {
go watch()
signalChan := make(chan os.Signal, 1)
signal.Notify(signalChan, syscall.SIGINT, syscall.SIGTERM)
<-signalChan
}
My code reads input from terminal and send those value to nats while it needs to have an http endpoint.
Separately it works but when I combine all of them it does not read from nats. If you could point me to a right direction I would appreciate.
package main
import (
"bufio"
"fmt"
nats "github.com/nats-io/nats.go"
"html/template"
"log"
"net/http"
"os"
)
func main() {
wd, err := os.Getwd()
if err != nil {
log.Fatal(err)
}
tmpl := template.Must(template.ParseFiles(wd + "/template/main.html"))
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
data := TodoPageData{
PageTitle: "Demo",
}
tmpl.Execute(w, data)
})
http.ListenAndServe(":8081", nil)
type message struct {
content string
}
var messages []message
nc, err := nats.Connect(
nats.DefaultURL,
)
if err != nil {
log.Fatal(err)
}
defer nc.Close()
// Subscribe
if _, err := nc.Subscribe("updates", func(m *nats.Msg) {
fmt.Printf("Received a message: %s\n", string(m.Data))
}); err != nil {
log.Fatal(err)
}
// io r/w
scanner := bufio.NewScanner(os.Stdin)
for scanner.Scan() {
if err := nc.Publish("updates", []byte(scanner.Text())); err != nil {
log.Fatal(err)
}
messages = append(messages, message{scanner.Text()})
for _, message := range messages {
fmt.Println(message.content)
}
}
if scanner.Err() != nil {
// handle error.
}
}
http.ListenAndServe is a blocking call. Start it on a new goroutine:
go http.ListenAndServe(":8081", nil)
I'm trying to create a client and a server using Go but for some reason the server reports the connection as "closed". As the code is trivial I can't think of anything wrong with my code. Any help is appreciated.
package main
import (
log "github.com/golang/glog"
"net/http"
"golang.org/x/net/websocket"
"time"
"flag"
)
type server struct {
payload chan string
}
// srv pushes the messages received via ws into srv.payload
func (srv *server) serve(ws *websocket.Conn) {
go func() {
var msg string
if err := websocket.Message.Receive(ws, &msg); err != nil {
log.Exit(err)
}
srv.payload <- msg
}()
return
}
// This example demonstrates a trivial client/ server.
func main() {
flag.Parse()
srv := server{payload: make(chan string, 10)}
http.Handle("/echo", websocket.Handler(srv.serve))
go func() {
err := http.ListenAndServe(":12345", nil)
if err != nil {
log.Errorf("ListenAndServe: " + err.Error())
}
}()
// give the server some time to start listening
time.Sleep(3 *time.Second)
//dial and test the response.
ws, err := websocket.Dial("ws://localhost:12345/echo", "", "http://localhost/?x=45")
if err != nil {
log.Exit(err)
}
ms := "test"
if err := websocket.Message.Send(ws, ms); err != nil {
log.Exit(err)
}
msg := <-srv.payload
if msg != ms{
log.Errorf("msg %v is not %v", ms)
}
}
Error
t.go:21] read tcp 127.0.0.1:12345->127.0.0.1:43135:
Edit:
After some try and error I've found that if I remove the go routine from the serve method it works but it doesn't make sense to me. Any idea why it doesn't work when websocket.Message.Receive is in a separate go routine?
package main
import (
log "github.com/golang/glog"
"net/http"
"golang.org/x/net/websocket"
"time"
"flag"
)
type server struct {
payload chan string
}
// srv pushes the messages received via ws into srv.payload
func (srv *server) serve(ws *websocket.Conn) {
var msg string
if err := websocket.Message.Receive(ws, &msg); err != nil {
log.Exit(err)
}
srv.payload <- msg
return
}
// This example demonstrates a trivial client/ server.
func main() {
flag.Parse()
srv := server{payload: make(chan string, 10)}
go func() {
http.Handle("/echo", websocket.Handler(srv.serve))
err := http.ListenAndServe(":12345", nil)
if err != nil {
log.Errorf("ListenAndServe: " + err.Error())
}
}()
// give the server some time to start listening
time.Sleep(3 *time.Second)
//dial and test the response.
ws, err := websocket.Dial("ws://localhost:12345/echo", "", "http://localhost/?x=45")
if err != nil {
log.Exit(err)
}
ms := "test"
if err := websocket.Message.Send(ws, ms); err != nil {
log.Exit(err)
}
msg := <-srv.payload
if msg != ms{
log.Errorf("msg %v is not %v", ms)
}
}
The websocket server closes the connection when the handler returns.
Removing the Go routine is the correct fix.