OpenTelemetry sidecar wait for client data flush - docker

I use open telemetry for tracing and metrics. I have a pretty standard setup - there is a service that produces metrics/traces and an open telemetry sidecar that collects these metrics and pushes them to AWS:
services:
service:
build:
context: .
image: service
container_name: service
ports:
- "3000:3000"
depends_on:
- aws-otel-collector
aws-otel-collector:
image: public.ecr.aws/aws-observability/aws-otel-collector:latest
container_name: aws-otel-collector
ports:
- "4317:4317"
Service flushes metrics and shuts down an exporter on service shutdown:
shutdown, err := initMetricProvider(ctx)
if err != nil {
log.Fatal(err)
}
defer func() {
log.Printf("Shutting down metric provider")
if err := shutdown(ctx); err != nil {
log.Fatal(fmt.Errorf("failed to shutdown metric provider: %w", err))
}
}()
meter := global.MeterProvider().Meter("service")
counter, err := meter.SyncInt64().Counter("test")
From time to time I am getting errors during restarts, caused by an inability to push metrics on a shutdown, smth like:
max retry time elapsed: rpc error: code = Unavailable desc = connection error: desc = "transport: Error while dialing dial tcp 127.0.0.1:4317: connect: connection refused"
This happens because the otel collector sidecar is getting suspended before metrics are flushed in service.
Question: how does one guarantees the sidecar waits until metrics are flushed? is there a way to have a delay on sidecar shutdown? (it didn't manage to find this in otel documentation)

Related

panic: dial tcp: lookup bookstoreDB on 172.22.64.1:53: no such host

First post here!
Trying to connect to a mysql server from docker using golang,gin, and gorm but I'm having issues connecting to the server through gorm.
Here is the error I am getting :
panic: dial tcp: lookup bookstoreDB on 172.22.64.1:53: no such host
Here is how I am trying to initiate the connection through gorm:
func Connect() {
d, err := gorm.Open("mysql", "docker:password#tcp(bookstoreDB)/bookstore")
if err != nil {
panic(err)
}
db = d
}
Here's what my docker-compose.yml file looks like:
version: "3.8"
services:
mysql_server:
image: mysql:8.0
container_name: bookstoreDB
environment:
- MYSQL_DATABASE=bookstore
- MYSQL_USER=docker
- MYSQL_PASSWORD=password
- MYSQL_ROOT_PASSWORD=password
ports:
- "3306:3306"
Here is what appears when I run the "docker-compose ps" command:
Name Command State Ports
-------------------------------------------------------------------------------------
bookstoreDB docker-entrypoint.sh mysqld Up 0.0.0.0:3306->3306/tcp, 33060/tcp
Here is a screenshot of my project structure :
bookstore project structure
Thank you for your time.
Here you are trying to connect to a hostname that is totally unknown out of the docker-compose cluster.
d, err := gorm.Open("mysql", "docker:password#tcp(bookstoreDB)/bookstore")
bookstoreDB is totally unknown here. The idea of mapping the ports (as you are doing with mySql's one :
Name Command State Ports
-------------------------------------------------------------------------------------
bookstoreDB docker-entrypoint.sh mysqld Up 0.0.0.0:3306->3306/tcp, 33060/tcp
Is to use that mapping as connection to the database (not the container's intra host name).
Change your code so you connect to your localhost:3306 instead. This is pseudocode as don't understand the language:
d, err := gorm.Open("mysql", "<docker:password#tcp(localhost)/bookstore>")

Dapr golang Docker Compose - running into a ""errorCode":"ERR_DIRECT_INVOKE","message":"invoke API is not ready" error

I am trying out Dapr for the first time ....refering to the Dapr go sdk at https://github.com/dapr/go-sdk...
... trying to host a Dapr service using golang with Docker Compose on my Windows 10 machine - using VSCode - and running into an issue connecting to ther service.
I have the docker compose file set to do a simple configuration as follows. And trying to connect to the service via the Dapr API using curl
golang service (taskapi service) => Dapr SideCar (taskapidapr)
I based it off of the example from https://github.com/dapr/go-sdk/blob/main/example/Makefile, but using Docker Compose.
When I try to connect connect to the service using
curl -d "ping" -H "Content-type: text/plain;charset=UTF-8"
"http://localhost:8300/v1.0/invoke/taskapi/method/echo"
I am running into the following error.
{"errorCode":"ERR_DIRECT_INVOKE","message":"invoke API is not ready"}
And the Dapr logs in Docker show a 'no mDNS apps to refresh.' - not sure if this is the cause of it and how to handle it.
Anyone can point me to what I am missing - greatly appreciate it.
Thank you
Athadu
golang package
package main
import (
"context"
"errors"
"fmt"
"log"
"net/http"
"github.com/dapr/go-sdk/service/common"
daprd "github.com/dapr/go-sdk/service/http"
)
func main() {
port := "8085"
address := fmt.Sprintf(":%s", port)
log.Printf("Creating New service at %v port", address)
log.Println()
// create a Dapr service (e.g. ":8080", "0.0.0.0:8080", "10.1.1.1:8080" )
s := daprd.NewService(address)
// add a service to service invocation handler
if err := s.AddServiceInvocationHandler("/echo", echoHandler); err != nil {
log.Fatalf("error adding invocation handler: %v", err)
}
if err := s.Start(); err != nil && err != http.ErrServerClosed {
log.Fatalf("error listenning: %v", err)
}
}
func echoHandler(ctx context.Context, in *common.InvocationEvent) (out *common.Content, err error) {
if in == nil {
err = errors.New("invocation parameter required")
return
}
log.Printf(
"echo - ContentType:%s, Verb:%s, QueryString:%s, %s",
in.ContentType, in.Verb, in.QueryString, in.Data,
)
out = &common.Content{
Data: in.Data,
ContentType: in.ContentType,
DataTypeURL: in.DataTypeURL,
}
return
}
docker-compose.yml
version: "3"
services:
taskapi:
image: golang:1.16
volumes:
- ..:/go/src/lekha
working_dir: /go/src/lekha/uploader
command: go run main.go
ports:
- "8085:8085"
environment:
aaa: 80
my: I am THE variable value
networks:
- lekha
taskapidapr:
image: "daprio/daprd:edge"
command: [
"./daprd",
"-app-id", "taskapi",
"-app-protocol", "http",
"-app-port", "8085",
"-dapr-http-port", "8300",
"-placement-host-address", "placement:50006",
"-log-level", "debug",
"-components-path", "/components"
]
volumes:
- "../dapr-components/:/components" # Mount our components folder for the dapr runtime to use
depends_on:
- taskapi
ports:
- "8300:8300"
networks:
- lekha
#network_mode: "service:taskapi" # Attach the task-api-dapr service to the task-api network namespace
############################
# Dapr placement service
############################
placement:
image: "daprio/dapr"
command: ["./placement", "-port", "50006"]
ports:
- "50006:50006"
networks:
- lekha
networks:
lekha:
Daprd shows these mDNS messages in logs - not sure if this is the cause
time="2021-05-24T01:06:13.6629303Z" level=debug msg="Refreshing all
mDNS addresses." app_id=taskapi instance=442e04c9e8a6
scope=dapr.contrib type=log ver=edge
time="2021-05-24T01:06:13.6630421Z" level=debug msg="no mDNS apps to
refresh." app_id=taskapi instance=442e04c9e8a6 scope=dapr.contrib
Additionally, I see the containers on the expected ports ... running fine in Docker desktop...
enter image description here
{
"errorCode": "ERR_DIRECT_INVOKE",
"message": "invoke API is not ready"
}
same as yours

Access Neo4J from another container

I am running a neo4j graph database inside a docker container. I've written another service in Go that should be able to execute queries from its respective container. I cannot however get the connection between those two containers established.
the dockerfile of my database:
version: "3"
services:
neo4j-db:
image: neo4j:latest
ports:
- "7474:7474"
- "7473:7473"
- "7687:7687"
expose:
- 7474
networks:
app_net:
ipv4_address: 172.18.18.10
volumes:
- //C/Users/<user>/Desktop/neoj4/4.0/config:/conf
networks:
app_net:
driver: bridge
driver_opts:
com.docker.network.enable_ipv6: "false"
ipam:
driver: default
config:
- subnet: 172.18.18.0/24
My neo4j.conf:
dbms.connector.https.advertised_address=localhost:7473
dbms.default_listen_address=0.0.0.0
dbms.connector.http.advertised_address=localhost:7474
dbms.memory.pagecache.size=512M
dbms.connector.bolt.advertised_address=127.18.18.10:7687
dbms.tx_log.rotation.retention_policy=100M size
dbms.directories.logs=/logs
And finally inside my Go container:
uri := "bolt://127.18.18.10:7687"
username := "neo4j"
password := "test"
var (
err error
driver neo4j.Driver
session neo4j.Session
result neo4j.Result
greeting interface{}
)
fmt.Println("Connecting to Neo4j")
driver, err = neo4j.NewDriver(uri, neo4j.BasicAuth(username, password, ""), useConsoleLogger(neo4j.ERROR))
if err != nil {
fmt.Println("ERROR:" , err)
}
defer driver.Close()
fmt.Println("Getting Session")
session, err = driver.Session(neo4j.AccessModeWrite)
if err != nil {
fmt.Println("ERROR:" , err)
}
defer session.Close()
When calling the function the execution gets stuck after fmt.Println("Getting Session") without throwing any errors for 30 seconds and then simply terminates.
I also made sure to have both containers on the same network (app_net). I can ping between the containers without issue. However, trying telnet from the go-container to neo4j yields Unable to connect to remote host: Connection refused.
I'm not sure what I'm doing wrong. Browser access on neo4j works and from what I see the containers are on the same network.
Any advice or ideas are greatly appreciated.
After spending some additional time, I've managed to get it working. I took the following steps:
Use the container's hostname as uri (i.e. "bolt://container_name").
Remove encryption to prevent a TLS error:
if driver, err = neo4j.NewDriver(uri, neo4j.BasicAuth(username, password, ""), func(config *neo4j.Config) {
config.Log = neo4j.ConsoleLogger(neo4j.ERROR)
config.Encrypted = false
}); err != nil {
return err
}
defer driver.Close()

How to fix dial tcp i/o timeout while calling public address in docker container?

I'm setting up a new container 'A' which is calling some endpoints from container 'B'. Why are these calls always return dial tcp 116.2.153.48:8082: i/o timeout?
The call from container 'A' is using public IP. All containers are deployed on the CentOS 7. Every container has own network with own database in this network. Also, the call which returns error works fine from any REST-API client, such Postman.
Nameservers in resolv.conf file has been changed to google's 8.8.8.8 and 8.8.4.4
Error: error="Post http://116.2.153.48:8082/new_user?email=eto#email.com: dial tcp 116.203.153.48:8082: i/o timeout"
Call from the program:
req, err := http.NewRequest(http.MethodPost, fmt.Sprintf("http://116.2.153.48:8082/new_user?email=%s", user.Email), nil)
if err != nil {
return err
}
httpClient := &http.Client{}
resp, err := httpClient.Do(req)
if err != nil {
return err
}
UPD:
Docker-compose of the first container:
payment-ms:
container_name: payment-ms
build:
context: .
dockerfile: Dockerfile
environment:
- DB_HOST=payment-ms-db
ports:
- 8082:8082
Docker-compose file of the second container:
user-ms:
container_name: user-ms
build:
context: .
dockerfile: Dockerfile
environment:
- DB_HOST=user-ms-db
ports:
- 8080:8080
depends_on:
user-ms-db:
condition: service_healthy
Also, on my local machine with MacOS everything works fine, problem reproducing only on VPS with CentOS7.
The problem was triggered by 2 issues.
First, containers must be in the same network. And the second one, when containers are in the same network, calls to each other must be with the property container name host. For example:
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
9c6c31b8ec21 user-ms "./user-ms run" 3 minutes ago Up 3 minutes 8080/tcp, 0.0.0.0:9980->9980/tcp user-ms
13863218f942 finance-ms "./finance-ms run" 3 minutes ago Up 3 minutes 0.0.0.0:9982->9982/tcp finance-ms
That's mean, what curl and all other calls from container user-ms to finance-ms must be with finance-ms:9982 address.

Connect to elasticsearch 6.4 running in Docker from golang host application

Go ES client https://godoc.org/gopkg.in/olivere/elastic.v6 throws the "no active connection found: no Elasticsearch node available" error when attempting to connect from OS X host to ES running in docker container.
There's many discussions on how to solve it in v5.*, however, I couldn't find anything for v6.4.
Docker-compose part:
elasticsearch:
image: elasticsearch:6.4.2
network_mode: "bridge"
expose:
- "9200"
- "9300"
volumes:
- ./es-data:/usr/share/elasticsearch/data
ports:
- "9200:9200"
- "9300:9300"
Go client call:
esClient, esClientErr :=
elastic.NewClient(elastic.SetURL("http://127.0.0.1:9200"))
if esClientErr != nil {
return nil, fmt.Errorf("Failed to connect to ES: %v", esClientErr)
}
Output:
2018/11/09 15:57:54 Failed to connect to ES: no active connection found: no Elasticsearch node available
exit status 1
UPDATE
Setting network.publish_host: "_local_" solved the problem. The publish_address is set to 127.0.0.1:9300 now.

Resources