Skip to content

Commit

Permalink
Merge branch 'main' into refactor-flakeguard-report
Browse files Browse the repository at this point in the history
  • Loading branch information
lukaszcl authored Dec 6, 2024
2 parents 6e82b1d + 1449c13 commit c8efe41
Show file tree
Hide file tree
Showing 56 changed files with 503 additions and 4,057 deletions.
14 changes: 13 additions & 1 deletion book/src/framework/components/blockchains/evm.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,5 +72,17 @@ Public: 0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266
Private: ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80
```

Test keys for `Besu` can be found [here](https://besu.hyperledger.org/23.4.1/private-networks/reference/accounts-for-testing)
For `Besu` keys are
```
Public: 0xfe3b557e8fb62b89f4916b721be55ceb828dbd73
Private: 0x8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63
Public: 0x627306090abaB3A6e1400e9345bC60c78a8BEf57
Private: 0xc87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3
Public: 0xf17f52151EbEF6C7334FAD080c5704D77216b732
Private: 0xae6ae8e5ccbfb04590405997ee2d52d2b330726137b875053c36d94e974d162f
```

More docs for `Besu` can be found [here](https://besu.hyperledger.org/private-networks/reference/accounts-for-testing)

5 changes: 3 additions & 2 deletions book/src/framework/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@
| CTF_CONFIGS | Path(s) to test config files. <br/>Can be more than one, ex.: smoke.toml,smoke_1.toml,smoke_2.toml.<br/>First filepath will hold all the merged values | Any valid TOML file path | - ||
| CTF_LOG_LEVEL | Harness log level | `info`, `debug`, `trace` | `info` | 🚫 |
| CTF_PROMTAIL_DEBUG | Set `true` if you are integrating with remote `Loki` push API to debug Promtail | `true`, `false` | `false` | 🚫 |
| CTF_IGNORE_CRITICAL_LOGS | Ignore all logs that has CRIT,FATAL or PANIC levels (Chainlink nodes only!) | `true`, `false` | `false` | 🚫 |
| CTF_CHAINLINK_IMAGE | Flag to override Chainlink Docker image in format $repository:$tag | $repository:$tag | - | 🚫 |
| CTF_JD_IMAGE | Job distributor service image in format $repository:$tag | $repository:$tag | - | 🚫 |
| LOKI_URL | URL to `Loki` push api, should be like`${host}/loki/api/v1/push` | URL | `http://host.docker.internal:3030/loki/api/v1/push` | 🚫 |
| LOKI_TENANT_ID | Streams all components logs to `Loki`, see params below | `string` | `promtail` | 🚫 |
| LOKI_BASIC_AUTH | Basic auth in format $user:$password | `$user:$password` | - | 🚫 |
| RESTY_DEBUG | Log all Resty client HTTP calls | `true`, `false` | `false` | 🚫 |
| CTF_IGNORE_CRITICAL_LOGS | Ignore all logs that has CRIT,FATAL or PANIC levels (Chainlink nodes only!) | `true`, `false` | `false` | 🚫 |
| CTF_CHAINLINK_IMAGE | Flag to override Chainlink Docker image in format $repository:$tag | $repository:$tag | - | 🚫 |
117 changes: 9 additions & 108 deletions book/src/lib.md
Original file line number Diff line number Diff line change
Expand Up @@ -252,38 +252,13 @@ Builder will read the location of chain configuration from env var named `PRIVAT

`net` is an instance of `blockchain.EVMNetwork`, which contains characteristics of the network and can be used to connect to it using an EVM client. `rpc` variable contains arrays of public and private RPC endpoints, where "private" means URL that's accessible from the same Docker network as the chain is running in.

# Using LogStream
## Logs
By default, we will save logs of all Docker containers running on the host machine, when the test ends (regardless whether it failed or succeeded). They will be available in the `./logs/<test-name><date>` directory. Same goes for dumping the databases of PostgresDBs
used by the Chainlink nodes. These will be saves in the `./db_dumps/<test-name><date>` directory.

LogStream is a package that allows to connect to a Docker container and then flush logs to configured targets. Currently 3 targets are supported:
## Loki and Grafana

- `file` - saves logs to a file in `./logs` folder
- `loki` - sends logs to Loki
- `in-memory` - stores logs in memory

It can be configured to use multiple targets at once. If no target is specified, it becomes a no-op.

LogStream has to be configured by passing an instance of `LoggingConfig` to the constructor.

When you connect a container LogStream will create a new consumer and start a detached goroutine that listens to logs emitted by that container and which reconnects and re-requests logs if listening fails for whatever reason. Retry limit and timeout can both be configured using functional options. In most cases one container should have one consumer, but it's possible to have multiple consumers for one container.

LogStream stores all logs in gob temporary file. To actually send/save them, you need to flush them. When you do it, LogStream will decode the file and send logs to configured targets. If log handling results in an error it won't be retried and processing of logs for given consumer will stop (if you think we should add a retry mechanism please let us know).

_Important:_ Flushing and accepting logs is blocking operation. That's because they both share the same cursor to temporary file and otherwise it's position would be racey and could result in mixed up logs.

## Configuration

Basic `LogStream` TOML configuration is following:

```toml
[LogStream]
log_targets=["file"]
log_producer_timeout="10s"
log_producer_retry_limit=10
```

You can find it here: [logging_default.toml](https://github.com/smartcontractkit/chainlink-testing-framework/blob/main/lib/config/tomls/logging_default.toml)

When using `in-memory` or `file` target no other configuration variables are required. When using `loki` target, following ones must be set:
If you need to pass Loki or Grafana configuration to your tests you can do that by providing the following config:

```toml
[Logging.Loki]
Expand All @@ -295,87 +270,13 @@ bearer_token_secret="bearer-token"

Also, do remember that different URL should be used when running in CI and everywhere else. In CI it should be a public endpoint, while in local environment it should be a private one.

If your test has a Grafana dashboard in order for the url to be correctly printed you should provide the following config:
If your test has a Grafana dashboard you should provide the following config:

```toml
[Logging.Grafana]
url="http://grafana.somwhere.com/my_dashboard"
```

## Initialisation

First you need to create a new instance:

```golang
// t - instance of *testing.T (can be nil)
// testConfig.Logging - pointer to logging part of TestConfig
ls := logstream.NewLogStream(t, testConfig.Logging)
```

## Listening to logs

If using `testcontainers-go` Docker containers it is recommended to use life cycle hooks for connecting and disconnecting LogStream from the container. You can do that when creating `ContainerRequest` in the following way:

```golang
containerRequest := &tc.ContainerRequest{
LifecycleHooks: []tc.ContainerLifecycleHooks{
{PostStarts: []tc.ContainerHook{
func(ctx context.Context, c tc.Container) error {
if ls != nil {
return n.ls.ConnectContainer(ctx, c, "custom-container-prefix-can-be-empty")
}
return nil
},
},
PostStops: []tc.ContainerHook{
func(ctx context.Context, c tc.Container) error {
if ls != nil {
return n.ls.DisconnectContainer(c)
}
return nil
},
}},
},
}
```

You can print log location for each target using this function: `(m *LogStream) PrintLogTargetsLocations()`. For `file` target it will print relative folder path, for `loki` it will print URL of a Grafana Dashboard scoped to current execution and container ids. For `in-memory` target it's no-op.

It is recommended to shutdown LogStream at the end of your tests. Here's an example:

```golang
t.Cleanup(func() {
l.Warn().Msg("Shutting down Log Stream")

if t.Failed() || os.Getenv("TEST_LOG_COLLECT") == "true" {
// we can't do much if this fails, so we just log the error
_ = logStream.FlushLogsToTargets()
// this will log log locations for each target (for file it will be a folder, for Loki Grafana dashboard -- remember to provide it's url in config!)
logStream.PrintLogTargetsLocations()
// this will save log locations in test summary, so that they can be easily accessed in GH's step summary
logStream.SaveLogLocationInTestSummary()
}

// we can't do much if this fails, so we just log the error
_ = logStream.Shutdown(testcontext.Get(b.t))
})
```

or in a bit shorter way:

```golang
t.Cleanup(func() {
l.Warn().Msg("Shutting down Log Stream")

if t.Failed() || os.Getenv("TEST_LOG_COLLECT") == "true" {
// this will log log locations for each target (for file it will be a folder, for Loki Grafana dashboard -- remember to provide it's url in config!)
logStream.PrintLogTargetsLocations()
// this will save log locations in test summary, so that they can be easily accessed in GH's step summary
}

// we can't do much if this fails
_ = logStream.FlushAndShutdown()
})
base_url="https://your-grafana-url"
dashboard_url="/my-dashboard"
dashboard_uid="my-dashboard-uid" # optional
```

## Grouping test execution
Expand Down
14 changes: 0 additions & 14 deletions book/src/lib/config/config.md
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,6 @@ convert_to_toml_array() {
}
selected_networks=$(convert_to_toml_array "$SELECTED_NETWORKS")
log_targets=$(convert_to_toml_array "$LOGSTREAM_LOG_TARGETS")
if [ -n "$PYROSCOPE_SERVER" ]; then
pyroscope_enabled=true
Expand All @@ -292,12 +291,6 @@ else
execution_layer="geth"
fi
if [ -n "$TEST_LOG_COLLECT" ]; then
test_log_collect=true
else
test_log_collect=false
fi
cat << EOF > config.toml
[Network]
selected_networks=$selected_networks
Expand All @@ -312,13 +305,6 @@ server_url="$PYROSCOPE_SERVER"
environment="$PYROSCOPE_ENVIRONMENT"
key_secret="$PYROSCOPE_KEY"
[Logging]
test_log_collect=$test_log_collect
run_id="$RUN_ID"
[Logging.LogStream]
log_targets=$log_targets
[Logging.Loki]
tenant_id="$LOKI_TENANT_ID"
url="$LOKI_URL"
Expand Down
3 changes: 3 additions & 0 deletions framework/.changeset/v0.3.3.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
- Upgrade Besu to 24.9.1
- Expose default test private keys as framework constants
- Collect all the logs even between restarts
1 change: 1 addition & 0 deletions framework/.changeset/v0.3.4.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- Bump go-ethereum as in core, fix darwin amd/arm binary release
8 changes: 7 additions & 1 deletion framework/components/blockchain/besu.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,15 @@ import (
"github.com/testcontainers/testcontainers-go/wait"
)

const (
DefaultBesuPrivateKey1 = "8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63"
DefaultBesuPrivateKey2 = "c87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3"
DefaultBesuPrivateKey3 = "ae6ae8e5ccbfb04590405997ee2d52d2b330726137b875053c36d94e974d162f"
)

func defaultBesu(in *Input) {
if in.Image == "" {
in.Image = "hyperledger/besu:22.1.0"
in.Image = "hyperledger/besu:24.9.1"
}
if in.ChainID == "" {
in.ChainID = "1337"
Expand Down
1 change: 1 addition & 0 deletions framework/components/blockchain/geth.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ const (
}
}
`
DefaultGethPrivateKey = `ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80`
)

var initScript = `
Expand Down
7 changes: 7 additions & 0 deletions framework/components/simple_node_set/reload.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
package simple_node_set

import (
"fmt"
"github.com/google/uuid"
"github.com/smartcontractkit/chainlink-testing-framework/framework"
"github.com/smartcontractkit/chainlink-testing-framework/framework/chaos"
"github.com/smartcontractkit/chainlink-testing-framework/framework/components/blockchain"
"time"
Expand All @@ -9,6 +12,10 @@ import (
// UpgradeNodeSet updates nodes configuration TOML files
// this API is discouraged, however, you can use it if nodes require restart or configuration updates, temporarily!
func UpgradeNodeSet(in *Input, bc *blockchain.Output, wait time.Duration) (*Output, error) {
uniq := fmt.Sprintf("%s-%s", framework.DefaultCTFLogsDir, uuid.NewString()[0:4])
if err := framework.WriteAllContainersLogs(uniq); err != nil {
return nil, err
}
_, err := chaos.ExecPumba("rm --volumes=false re2:^node.*|ns-postgresql.*", wait)
if err != nil {
return nil, err
Expand Down
4 changes: 2 additions & 2 deletions framework/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,9 +130,9 @@ func Load[X any](t *testing.T) (*X, error) {
t.Cleanup(func() {
err := Store[X](input)
require.NoError(t, err)
err = WriteAllContainersLogs()
err = WriteAllContainersLogs(DefaultCTFLogsDir)
require.NoError(t, err)
err = checkNodeLogErrors(DefaultCTFLogsDir)
err = checkAllNodeLogErrors()
require.NoError(t, err)
})
// TODO: not all the people have AWS access, sadly enough, uncomment when granted
Expand Down
12 changes: 6 additions & 6 deletions framework/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import (
)

const (
DefaultCTFLogsDir = "logs"
DefaultCTFLogsDir = "logs/docker"
)

func IsDockerRunning() bool {
Expand Down Expand Up @@ -189,11 +189,11 @@ func isLocalToolDockerContainer(containerName string) bool {
}

// WriteAllContainersLogs writes all Docker container logs to the default logs directory
func WriteAllContainersLogs() error {
func WriteAllContainersLogs(dir string) error {
L.Info().Msg("Writing Docker containers logs")
if _, err := os.Stat(DefaultCTFLogsDir); os.IsNotExist(err) {
if err := os.MkdirAll(DefaultCTFLogsDir, 0755); err != nil {
return fmt.Errorf("failed to create directory %s: %w", DefaultCTFLogsDir, err)
if _, err := os.Stat(dir); os.IsNotExist(err) {
if err := os.MkdirAll(dir, 0755); err != nil {
return fmt.Errorf("failed to create directory %s: %w", dir, err)
}
}
provider, err := tc.NewDockerProvider()
Expand All @@ -220,7 +220,7 @@ func WriteAllContainersLogs() error {
L.Error().Err(err).Str("Container", containerName).Msg("failed to fetch logs for container")
return err
}
logFilePath := filepath.Join(DefaultCTFLogsDir, fmt.Sprintf("%s.log", containerName))
logFilePath := filepath.Join(dir, fmt.Sprintf("%s.log", containerName))
logFile, err := os.Create(logFilePath)
if err != nil {
L.Error().Err(err).Str("Container", containerName).Msg("failed to create container log file")
Expand Down
2 changes: 1 addition & 1 deletion framework/examples/myproject/smoke.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
[blockchain_a]
# choose "anvil", "geth" or "besu"
# uncomment the second line for "anvil"
type = "geth"
type = "besu"
# docker_cmd_params = ["-b", "1"]

[data_provider]
Expand Down
7 changes: 3 additions & 4 deletions framework/go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ require (
github.com/davecgh/go-spew v1.1.1
github.com/docker/docker v27.1.1+incompatible
github.com/docker/go-connections v0.5.0
github.com/ethereum/go-ethereum v1.13.8
github.com/ethereum/go-ethereum v1.14.11
github.com/gin-gonic/gin v1.10.0
github.com/go-playground/validator/v10 v10.22.1
github.com/go-resty/resty/v2 v2.15.3
Expand Down Expand Up @@ -69,7 +69,7 @@ require (
github.com/cpuguy83/dockercfg v0.3.2 // indirect
github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect
github.com/crate-crypto/go-ipa v0.0.0-20240223125850-b1e8a79f509c // indirect
github.com/crate-crypto/go-kzg-4844 v0.7.0 // indirect
github.com/crate-crypto/go-kzg-4844 v1.0.0 // indirect
github.com/creack/pty v1.1.21 // indirect
github.com/deckarep/golang-set/v2 v2.6.0 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect
Expand All @@ -78,6 +78,7 @@ require (
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect
github.com/ethereum/c-kzg-4844 v1.0.0 // indirect
github.com/ethereum/go-verkle v0.1.1-0.20240829091221-dffa7562dbe9 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/gabriel-vasile/mimetype v1.4.6 // indirect
Expand Down Expand Up @@ -158,5 +159,3 @@ replace (

github.com/sourcegraph/sourcegraph/lib => github.com/sourcegraph/sourcegraph-public-snapshot/lib v0.0.0-20240822153003-c864f15af264
)

exclude github.com/crate-crypto/go-kzg-4844 v1.0.0
Loading

0 comments on commit c8efe41

Please sign in to comment.