Giter VIP home page Giter VIP logo

fthelper's Introduction

fthelper's People

Contributors

dependabot[bot] avatar github-actions[bot] avatar kamontat avatar prangnt avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

fthelper's Issues

[Bug]: No Data on Grafana

Module

fthelper

Version

v5.0.0-beta.12

What happened?

Probably it's not a bug but some configuration faults by my side. Tried to follow the blog post, not sure if it's still valid with latest version though. The issue must be on prometheus, simply a 'no data' issue. freqtrade itself, freqUI, grafana and ftmetric works as expected but the prometheus. on grafana, data source is added and approved, no any extraordinary errors under docker-compose logs but unhealthy tag on freqtrade's container.

Relevant log output

No response

Docker compose configuration

version: "3"

volumes:
  grafana-data:
  prometheus-data:

services:
  freqtrade:
    image: freqtradeorg/freqtrade:develop_plot
    container_name: freqtrade
    restart: on-failure
    ports:
      - 8081:8081
    volumes:
      - ./user_data:/freqtrade/user_data
    command: >
      trade 
        --logfile "/freqtrade/user_data/logs/freqtrade.log"
        --config "/freqtrade/user_data/config.json"
        --db-url sqlite:////freqtrade/user_data/tradesv3.sqlite
        --strategy BB_RPB_TSL_RNG_TBS_stashtra
    healthcheck:
      test: ["CMD-SHELL", "python3 /freqtrade/scripts/rest_client.py --config /freqtrade/user_data/config-rest.json version | grep -q version"]
      interval: 30s
      timeout: 4s
      retries: 3
#      start_period: 1m
  # single mode
  ftmetric:
    image: ghcr.io/kamontat/ftmetric:v5.0.0-beta.12
    container_name: ftmetric
    restart: on-failure
    environment:
      - FTH_INTERNAL__LOG__LEVEL=3 # 0=silent, 1=error, 2=warn, 3=info, 4=debug

      - FTH_FREQTRADE__HTTP__ENABLED=true
      - FTH_FREQTRADE__HTTP__URL=http://freqtrade:8081
      - FTH_FREQTRADE__HTTP__USERNAME=Freqtrader
      - FTH_FREQTRADE__HTTP__PASSWORD=SuperSecurePassword

      - FTH_FREQTRADE__DB__ENABLED=false
      - FTH_FREQTRADE__DB__TYPE=postgres
      - FTH_FREQTRADE__DB__URL=postgres:5432
      - FTH_FREQTRADE__DB__USERNAME=freqtrade
      - FTH_FREQTRADE__DB__NAME=database_name
      - FTH_FREQTRADE__DB__PASSWORD=password

      - FTH_SERVER__PORT=8090
    depends_on:
      - freqtrade
    healthcheck:
      test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:8090/healthcheck"]
      interval: 20s
      timeout: 1s
      retries: 3
#      start_period: 20s
  # cluster mode
  #ftmetricct:
  #  image: ghcr.io/kamontat/ftmetric:v5.0.0-beta.12
  #  container_name: ftmetricct
  #  restart: on-failure
  #  environment:
  #    - FTH_INTERNAL__LOG__LEVEL=3 # enabled info log
  #    - FTH_CLUSTERS=1A,2A

  #    - FTC_1A__FREQTRADE__HTTP__ENABLED=true
  #    - FTC_1A__FREQTRADE__HTTP__URL=http://freqtrade:8080
  #    - FTC_1A__FREQTRADE__HTTP__USERNAME=freqtrade
  #    - FTC_1A__FREQTRADE__HTTP__PASSWORD=password
  #    - FTC_1A__FREQTRADE__DB__ENABLED=false
  #    - FTC_1A__FREQTRADE__DB__TYPE=postgres
  #    - FTC_1A__FREQTRADE__DB__URL="localhost:5432"
  #    - FTC_1A__FREQTRADE__DB__NAME="freqtrade"
  #    - FTC_1A__FREQTRADE__DB__USERNAME="freqtrade"
  #    - FTC_1A__FREQTRADE__DB__PASSWORD="password"

  #    - FTC_2A__FREQTRADE__HTTP__ENABLED=true
  #    - FTC_2A__FREQTRADE__HTTP__URL="http://localhost:8081"
  #    - FTC_2A__FREQTRADE__HTTP__USERNAME="freqtrade"
  #    - FTC_2A__FREQTRADE__HTTP__PASSWORD="password"
  #    - FTC_2A__FREQTRADE__DB__ENABLED=false

  #    - FTH_SERVER__PORT=8090
  prometheus:
    image: prom/prometheus:v2.28.0
    restart: on-failure
    # be aware before open the port
    ports:
      - 9090:9090
    volumes:
      # TODO: add configuration at prometheus/prometheus.yml
      - ./prometheus:/etc/prometheus/
      - prometheus-data:/prometheus
    command:
      - "--config.file=/etc/prometheus/prometheus.yml"
    extra_hosts:
      - "host.docker.internal:host-gateway"
    healthcheck:
      test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:9090/-/healthy"]
      interval: 1m
      timeout: 1s
      retries: 3
#      start_period: 15s
  grafana:
    image: grafana/grafana:8.0.3
    container_name: grafana
    restart: on-failure
    ports:
      - 3000:3000
    depends_on:
      - freqtrade
      - prometheus
    volumes:
      - prometheus-data:/prometheus
    environment:
      ## override server url
      # - GF_SERVER_ROOT_URL=http://example.com
      - GF_SERVER_HTTP_PORT=3000
      ## enabled grafana beta alert manager
      # - GF_FEATURE_TOGGLES_ENABLE=ngalert
      - GF_SECURITY_ADMIN_USER=admin
      - GF_SECURITY_ADMIN_PASSWORD=verygrafanapassword
    healthcheck:
      test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:3000/api/health"]
      interval: 1m
      timeout: 1s
      retries: 3
#      start_period: 15s

[feature]: Add profit of currently opened trades.

Feature request

Is your feature request related to a problem?

A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

Describe the solution you'd like

A clear and concise description of what you want to happen.

Additional context

Add any other context or screenshots about the feature request here.

[BUG]: runtime error: invalid memory address or nil pointer dereference

run into this issue and cant say what this issue caused:

21:15:28 map:merger           [DEBUG] | merging key=name from fr******e -> fre*********r
21:15:28 map:merger           [DEBUG] | merging key=name from fr******e -> fre*********h
21:15:28 map:merger           [DEBUG] | merging key=username from fre********R -> fre********H
21:15:28 map:merger           [DEBUG] | merging key=password from Supe*************rd -> $n3********z
21:15:28 map:merger           [DEBUG] | merging key=name from fr******e -> fre*********dt
21:15:28 map:merger           [DEBUG] | merging key=password from Supe*************rd -> $n3********z
21:15:28 map:merger           [DEBUG] | merging key=username from fre********R -> fre*********T
21:15:28 map:merger           [DEBUG] | merging key=url from http:*****************080 -> http:/*****************080
21:15:28 map:merger           [DEBUG] | merging key=name from fr******e -> fre*********dt
21:15:28 map:merger           [DEBUG] | merging key=username from fre********R -> hy*****R
21:15:28 map:merger           [DEBUG] | merging key=url from http:*****************080 -> http:/*****************8080
21:15:28 map:merger           [DEBUG] | merging key=password from Supe*************rd -> $n3********z
21:15:28 map:merger           [DEBUG] | merging key=url from http:*****************080 -> http:/******************8080
21:15:28 map:merger           [DEBUG] | merging key=username from fre********R -> hy******T
21:15:28 map:merger           [DEBUG] | merging key=password from Supe*************rd -> $n3********z
21:15:28 map:merger           [DEBUG] | merging key=name from fr******e -> fre*********dt
21:15:28 command:default      [INFO ] | [with-cache] Connection cluster '1A'
  http     - http://freqtrade-eur:8080 'freqtradeEUR:Supe*************rd'
  database - disabled
21:15:28 command:default      [INFO ] | [with-cache] Connection cluster '2A'
  http     - http://freqtrade-eth:8080 'freqtradeETH:$n3********z'
  database - disabled
21:15:28 command:default      [INFO ] | [with-cache] Connection cluster '3A'
  http     - http://freqtrade-usdt:8080 'freqtradeUSDT:$n3********z'
  database - disabled
21:15:28 command:default      [INFO ] | [with-cache] Connection cluster '4A'
  http     - http://freqtrade-bteur:8080 'hyperEUR:$n3********z'
  database - disabled
21:15:28 command:default      [INFO ] | [with-cache] Connection cluster '5A'
  http     - http://freqtrade-btusdt:8080 'hyperUSDT:$n3********z'
  database - disabled
21:15:28 client:http:1A       [DEBUG] | request: GET http://freqtrade-eur:8080/api/v1/ping
21:15:28 cache:service        [DEBUG] | creating 'http.total-call.1A' data
21:15:28 cache:service        [DEBUG] | creating 'http.success-call.1A' data

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x18 pc=0x88e2f2]

goroutine 1 [running]:
github.com/kamontat/fthelper/metric/v4/src/clients.(*Http).handleError(0xc0002097a0, 0x0, 0x0, 0xafe8e0, 0xc00000e190)
        /home/runner/work/fthelper/fthelper/metric/src/clients/http.go:39 +0x52
github.com/kamontat/fthelper/metric/v4/src/clients.(*Http).Initial(0xc0002097a0, 0x80, 0x80)
        /home/runner/work/fthelper/fthelper/metric/src/clients/http.go:45 +0xb0
github.com/kamontat/fthelper/metric/v4/src/freqtrade.(*Freqtrade).Initial(0xc00029f170, 0xc0002a2100, 0xc000298b20)
        /home/runner/work/fthelper/fthelper/metric/src/freqtrade/freqtrade.go:29 +0x47
github.com/kamontat/fthelper/metric/v4/src/connection.(*cache).Initial(0xc0002a0040, 0xc0002a0100, 0x4)
        /home/runner/work/fthelper/fthelper/metric/src/connection/cache.go:33 +0x76
main.defaultCommand(0xc00001f9a0, 0x203000, 0xc00002b000)
        /home/runner/work/fthelper/fthelper/metric/main.go:52 +0x3b3
github.com/kamontat/fthelper/shared/commandline/commands.(*Command).Start(0xc00002a360, 0xc00001f9a0, 0x2, 0xc00002b000)
        /home/runner/work/fthelper/fthelper/shared/commandline/commands/command.go:27 +0x5a
github.com/kamontat/fthelper/shared/commandline.(*cli).Start(0xc000020540, 0xc0000b0000, 0x5, 0x5, 0xc000066568, 0xc000050930)
        /home/runner/work/fthelper/fthelper/shared/commandline/cli.go:87 +0x9b2
main.main()
        /home/runner/work/fthelper/fthelper/metric/main.go:97 +0x477

[feature]: Populating initial data on prometheus

Feature request

Is your feature request related to a problem?

When ftmetrics+prometheus+grafa is started, there is no initial data for balance and profit calculation

Describe the solution you'd like

A way to populate initial data from freqtrade sqlite, so that even after a prometheus data reset, monitoring can continue as before

[BUG]: ftmetric service restarts | connection refused (docker)

the metric service cant connect to freqtrade service port 8080:

Get "http://localhost:8080/api/v1/ping": dial tcp 127.0.0.1:8080: connect: connection refused

Connecting myself to the given adress i can get the "pong" result from the API.

curl http://localhost:8080/api/v1/ping
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100    17  100    17    0     0   4406      0 --:--:-- --:--:-- --:--:--  5666

{"status":"pong"}

is the service really looking not "inside" due to 127.0.0.1 ??? so i also tried with my client adress since running freqtrade on my local machine but my config looks like:

"api_server": {
        "enabled": true,
        "listen_ip_address": "0.0.0.0",
        "listen_port": 8080,
        "verbosity": "error",
        "enable_openapi": false,
        "jwt_secret_key": "STRONG KEY",
        "CORS_origins": ["http://127.0.0.1","http://192.x.x.x","http://localhost","http://192.x.x.y"],
        "username": "username",
        "password": "password"
    },
22:24:00 client:db            [ERROR] | error: failed to connect to `host=localhost user= database=freqtrade`: dial error (dial tcp [::1]:5432: connect: cannot assign requested address)
panic: found '1' errors (total=2)
- Get "http://localhost:8080/api/v1/ping": dial tcp 127.0.0.1:8080: connect: connection refused


goroutine 1 [running]:
main.defaultCommand(0xc0000b49b0, 0x203000, 0xc00009f060)
        /home/runner/work/fthelper/fthelper/metric/main.go:55 +0x81a
github.com/kamontat/fthelper/shared/commandline/commands.(*Command).Start(0xc00009e320, 0xc0000b49b0, 0x2, 0xc00009f060)
        /home/runner/work/fthelper/fthelper/shared/commandline/commands/command.go:27 +0x5a
github.com/kamontat/fthelper/shared/commandline.(*cli).Start(0xc0000c4500, 0xc00001e0a0, 0x5, 0x5, 0xc000094568, 0xc00009c930)
        /home/runner/work/fthelper/fthelper/shared/commandline/cli.go:87 +0x9b2
main.main()
        /home/runner/work/fthelper/fthelper/metric/main.go:97 +0x477

docker inspect:

"Id": "41f243ac5e59b5f4fc055f431945b28a47e076fec68f23c785b8c936be0d324a",
    "Created": "2021-10-17T22:25:43.609797739Z",
    "Path": "/fth/ftmetric",
    "Args": [
        "--pwd",
        "/fth",
        "--envs",
        "/fth/.env.docker"
    ],
    "State": {
        "Status": "restarting",
        "Running": true,
        "Paused": false,
        "Restarting": true,
        "OOMKilled": false,
        "Dead": false,
        "Pid": 0,
        "ExitCode": 2,
        "Error": "",
        "StartedAt": "2021-10-17T22:26:48.935172108Z",
        "FinishedAt": "2021-10-17T22:26:48.953706053Z",
        "Health": {
            "Status": "unhealthy",
            "FailingStreak": 0,
            "Log": []
        }
    },
    "Image": "sha256:b700bffaf79d67e0da292e590f7dd0220d678e6d644ef724871fa8fcb03efdde",
    "ResolvConfPath": "/var/lib/docker/containers/41f243ac5e59b5f4fc055f431945b28a47e076fec68f23c785b8c936be0d324a/resolv.conf",
    "HostnamePath": "/var/lib/docker/containers/41f243ac5e59b5f4fc055f431945b28a47e076fec68f23c785b8c936be0d324a/hostname",
    "HostsPath": "/var/lib/docker/containers/41f243ac5e59b5f4fc055f431945b28a47e076fec68f23c785b8c936be0d324a/hosts",
    "LogPath": "/var/lib/docker/containers/41f243ac5e59b5f4fc055f431945b28a47e076fec68f23c785b8c936be0d324a/41f243ac5e59b5f4fc055f431945b28a47e076fec68f23c785b8c936be0d324a-json.log",
    "Name": "/ftmetric",
    "RestartCount": 10,
    "Driver": "overlay2",
    "Platform": "linux",
    "MountLabel": "",
    "ProcessLabel": "",
    "AppArmorProfile": "",
    "ExecIDs": null,
    "HostConfig": {
        "Binds": [],
        "ContainerIDFile": "",
        "LogConfig": {
            "Type": "json-file",
            "Config": {}
        },
        "NetworkMode": "ft_userdata_default",
        "PortBindings": {},
        "RestartPolicy": {
            "Name": "on-failure",
            "MaximumRetryCount": 0
        },
        "AutoRemove": false,
        "VolumeDriver": "",
        "VolumesFrom": null,
        "CapAdd": null,
        "CapDrop": null,
        "CgroupnsMode": "host",
        "Dns": null,
        "DnsOptions": null,
        "DnsSearch": null,
        "ExtraHosts": null,
        "GroupAdd": null,
        "IpcMode": "private",
        "Cgroup": "",
        "Links": null,
        "OomScoreAdj": 0,
        "PidMode": "",
        "Privileged": false,
        "PublishAllPorts": false,
        "ReadonlyRootfs": false,
        "SecurityOpt": null,
        "UTSMode": "",
        "UsernsMode": "",
        "ShmSize": 67108864,
        "Runtime": "runc",
        "ConsoleSize": [
            0,
            0
        ],
        "Isolation": "",
        "CpuShares": 0,
        "Memory": 0,
        "NanoCpus": 0,
        "CgroupParent": "",
        "BlkioWeight": 0,
        "BlkioWeightDevice": null,
        "BlkioDeviceReadBps": null,
        "BlkioDeviceWriteBps": null,
        "BlkioDeviceReadIOps": null,
        "BlkioDeviceWriteIOps": null,
        "CpuPeriod": 0,
        "CpuQuota": 0,
        "CpuRealtimePeriod": 0,
        "CpuRealtimeRuntime": 0,
        "CpusetCpus": "",
        "CpusetMems": "",
        "Devices": null,
        "DeviceCgroupRules": null,
        "DeviceRequests": null,
        "KernelMemory": 0,
        "KernelMemoryTCP": 0,
        "MemoryReservation": 0,
        "MemorySwap": 0,
        "MemorySwappiness": null,
        "OomKillDisable": false,
        "PidsLimit": null,
        "Ulimits": null,
        "CpuCount": 0,
        "CpuPercent": 0,
        "IOMaximumIOps": 0,
        "IOMaximumBandwidth": 0,
        "MaskedPaths": [
            "/proc/asound",
            "/proc/acpi",
            "/proc/kcore",
            "/proc/keys",
            "/proc/latency_stats",
            "/proc/timer_list",
            "/proc/timer_stats",
            "/proc/sched_debug",
            "/proc/scsi",
            "/sys/firmware"
        ],
        "ReadonlyPaths": [
            "/proc/bus",
            "/proc/fs",
            "/proc/irq",
            "/proc/sys",
            "/proc/sysrq-trigger"
        ]
    },
    "GraphDriver": {
        "Data": {
            "LowerDir": "/var/lib/docker/overlay2/9263036bfcae0acc7bc54da75a8311bdd675b21cb69718108b2f8cad632cdd3f-init/diff:/var/lib/docker/overlay2/0767a8a8ff74895307bbf27cc86b0d7ee3cbaa8268d0c0a913945f751402d431/diff:/var/lib/docker/overlay2/ca9e3451d87329849ba44ac450cde79db54715ca8dbb26e37f8e0f83ec1f6843/diff:/var/lib/docker/overlay2/c6b495106ad2d9f8e2136cac22a1315bc9c688ed12e28e5c68b7ec63abdabd34/diff:/var/lib/docker/overlay2/ba877a38c09c65d784390c739daf02afbd66e82b3419ad4171ee3b7df84c8d8b/diff",
            "MergedDir": "/var/lib/docker/overlay2/9263036bfcae0acc7bc54da75a8311bdd675b21cb69718108b2f8cad632cdd3f/merged",
            "UpperDir": "/var/lib/docker/overlay2/9263036bfcae0acc7bc54da75a8311bdd675b21cb69718108b2f8cad632cdd3f/diff",
            "WorkDir": "/var/lib/docker/overlay2/9263036bfcae0acc7bc54da75a8311bdd675b21cb69718108b2f8cad632cdd3f/work"
        },
        "Name": "overlay2"
    },
    "Mounts": [],
    "Config": {
        "Hostname": "41f243ac5e59",
        "Domainname": "",
        "User": "",
        "AttachStdin": false,
        "AttachStdout": true,
        "AttachStderr": true,
        "Tty": false,
        "OpenStdin": false,
        "StdinOnce": false,
        "Env": [
            "FTH_FREQTRADE__PASSWORD=password",
            "FTH_FREQTRADE__URL=http://freqtrade:8080",
            "FTH_FREQTRADE__USERNAME=username",
            "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
        ],
        "Cmd": null,
        "Healthcheck": {
            "Test": [
                "CMD",
                "wget",
                "--no-verbose",
                "--tries=1",
                "--spider",
                "http://localhost:8090/version"
            ],
            "Interval": 60000000000,
            "Timeout": 1000000000,
            "StartPeriod": 15000000000,
            "Retries": 3
        },
        "Image": "ghcr.io/kamontat/ftmetric",
        "Volumes": null,
        "WorkingDir": "/fth",
        "Entrypoint": [
            "/fth/ftmetric",
            "--pwd",
            "/fth",
            "--envs",
            "/fth/.env.docker"
        ],
        "OnBuild": null,
        "Labels": {
            "com.docker.compose.config-hash": "1d6dfce3ecf90d5ab9a1c3500551c4e1ac294a07d375bb21f5d69f4a67b07eef",
            "com.docker.compose.container-number": "1",
            "com.docker.compose.depends_on": "freqtrade",
            "com.docker.compose.image": "sha256:b700bffaf79d67e0da292e590f7dd0220d678e6d644ef724871fa8fcb03efdde",
            "com.docker.compose.oneoff": "False",
            "com.docker.compose.project": "ft_userdata",
            "com.docker.compose.project.config_files": "D:\\freqtrade\\ft_userdata\\docker-compose.yml",
            "com.docker.compose.project.working_dir": "D:\\freqtrade\\ft_userdata",
            "com.docker.compose.service": "ftmetric",
            "com.docker.compose.version": "2.0.0",
            "org.opencontainers.image.created": "2021-09-20T15:45:49Z",
            "org.opencontainers.image.revision": "9a02bd3fbed0bb82e7ad949701e26aa66ae2e23d",
            "org.opencontainers.image.tag": "v5.0.0-beta.14",
            "org.opencontainers.image.title": "ftmetric",
            "org.opencontainers.image.version": "5.0.0-beta.14"
        }
    },
    "NetworkSettings": {
        "Bridge": "",
        "SandboxID": "5d8cfddde2f2fbfadd025593b39bea23ee4b0e9e1c5565c803eb2b21e574d84a",
        "HairpinMode": false,
        "LinkLocalIPv6Address": "",
        "LinkLocalIPv6PrefixLen": 0,
        "Ports": {},
        "SandboxKey": "/var/run/docker/netns/5d8cfddde2f2",
        "SecondaryIPAddresses": null,
        "SecondaryIPv6Addresses": null,
        "EndpointID": "",
        "Gateway": "",
        "GlobalIPv6Address": "",
        "GlobalIPv6PrefixLen": 0,
        "IPAddress": "",
        "IPPrefixLen": 0,
        "IPv6Gateway": "",
        "MacAddress": "",
        "Networks": {
            "ft_userdata_default": {
                "IPAMConfig": null,
                "Links": null,
                "Aliases": [
                    "ftmetric",
                    "ftmetric",
                    "41f243ac5e59"
                ],
                "NetworkID": "0baeeccd8042ce6337b657261033ef05a06a441b9f2ac8a4822b8ed6b53b4123",
                "EndpointID": "",
                "Gateway": "",
                "IPAddress": "",
                "IPPrefixLen": 0,
                "IPv6Gateway": "",
                "GlobalIPv6Address": "",
                "GlobalIPv6PrefixLen": 0,
                "MacAddress": "",
                "DriverOpts": null
            }
        }
    },
    "CreatedTime": 1634509543609
}
goroutine 1 [running]:
main.defaultCommand(0xc00001eaa0, 0x203000, 0xc00002d180)
        /home/runner/work/fthelper/fthelper/metric/main.go:55 +0x81a
github.com/kamontat/fthelper/shared/commandline/commands.(*Command).Start(0xc00002c360, 0xc00001eaa0, 0x2, 0xc00002d180)
        /home/runner/work/fthelper/fthelper/shared/commandline/commands/command.go:27 +0x5a
github.com/kamontat/fthelper/shared/commandline.(*cli).Start(0xc000184500, 0xc0000b2000, 0x5, 0x5, 0xc000068498, 0xc000052930)
        /home/runner/work/fthelper/fthelper/shared/commandline/cli.go:87 +0x9b2
main.main()
        /home/runner/work/fthelper/fthelper/metric/main.go:97 +0x477
23:00:27 command:default      [INFO ] | [with-cache] Connection cluster ''
  http     - http://localhost:8080 ':'
  database - localhost:5432 (postgres) ':'
23:00:27 client:http          [DEBUG] | request: GET http://localhost:8080/api/v1/ping
23:00:27 cache:service        [DEBUG] | creating 'http.total-call' data
23:00:27 client:http          [DEBUG] | error: Get "http://localhost:8080/api/v1/ping": dial tcp 127.0.0.1:8080: connect: connection refused
23:00:27 cache:service        [DEBUG] | creating 'http.failure-call' data
23:00:27 client:db            [ERROR] | error: failed to connect to `host=localhost user= database=freqtrade`: dial error (dial tcp [::1]:5432: connect: cannot assign requested address)
panic: found '1' errors (total=2)
- Get "http://localhost:8080/api/v1/ping": dial tcp 127.0.0.1:8080: connect: connection refused

[BUG]: Config env override not working for server port ft_metric

Bug report

Describe the bug

After overriding configured port from default 8090 to 8091 with -e "FTH_SERVER__PORT=8091" it still runs under port 8090

To Reproduce

Steps to reproduce the behavior:

  1. docker run --rm -it -p 8091:8091 -e "FTH_FREQTRADE__URL=http://freqtrade1:8081" -e "FTH_FREQTRADE__USERNAME=freqtrader" -e "FTH_FREQTRADE__PASSWORD=secret" -e "FTH_SERVER__PORT=8091" -e "FTH_FREQTRADE__CLUSTER=1A" --network="ft_grafana_default" ghcr.io/kamontat/ftmetric:latest --debug
  2. Check http://127.0.0.1:8091/metrics

Expected behavior

metrics available under port 9091

Information

Try to complete information as much as possible.

  1. Desktop:
  • OS: WIndows 10 / WSL2 Ubuntu 20.04

[BUG]: dial tcp 127.0.0.1:8080: connect: connection refused

where does this come from? i have added to the version 4.3.0 a .env.docker file with the specific clusters, i dont have any idea where this is coming from the container itself.

19:57:45 freqtrade:connection [WARN ] | Get "http://localhost:8080/api/v1/profit": dial tcp 127.0.0.1:8080: connect: connection refused
19:57:45 freqtrade:connection [WARN ] | Get "http://localhost:8080/api/v1/version": dial tcp 127.0.0.1:8080: connect: connection refused
19:57:45 freqtrade:connection [WARN ] | Get "http://localhost:8080/api/v1/show_config": dial tcp 127.0.0.1:8080: connect: connection refused
19:57:45 freqtrade:connection [WARN ] | Get "http://localhost:8080/api/v1/profit": dial tcp 127.0.0.1:8080: connect: connection refused
19:57:45 freqtrade:connection [WARN ] | Get "http://localhost:8080/api/v1/version": dial tcp 127.0.0.1:8080: connect: connection refused
19:57:45 freqtrade:connection [WARN ] | Get "http://localhost:8080/api/v1/show_config": dial tcp 127.0.0.1:8080: connect: connection refused
19:57:45 freqtrade:connection [WARN ] | Get "http://localhost:8080/api/v1/profit": dial tcp 127.0.0.1:8080: connect: connection refused
19:57:45 freqtrade:connection [WARN ] | Get "http://localhost:8080/api/v1/version": dial tcp 127.0.0.1:8080: connect: connection refused
19:57:45 freqtrade:connection [WARN ] | Get "http://localhost:8080/api/v1/show_config": dial tcp 127.0.0.1:8080: connect: connection refused
19:57:45 freqtrade:connection [WARN ] | Get "http://localhost:8080/api/v1/profit": dial tcp 127.0.0.1:8080: connect: connection refused
19:57:45 freqtrade:connection [WARN ] | Get "http://localhost:8080/api/v1/version": dial tcp 127.0.0.1:8080: connect: connection refused
19:57:45 freqtrade:connection [WARN ] | Get "http://localhost:8080/api/v1/show_config": dial tcp 127.0.0.1:8080: connect: connection refused
19:57:45 freqtrade:connection [WARN ] | Get "http://localhost:8080/api/v1/profit": dial tcp 127.0.0.1:8080: connect: connection refused
19:57:45 freqtrade:connection [WARN ] | Get "http://localhost:8080/api/v1/version": dial tcp 127.0.0.1:8080: connect: connection refused
19:57:45 freqtrade:connection [WARN ] | Get "http://localhost:8080/api/v1/show_config": dial tcp 127.0.0.1:8080: connect: connection refused
19:57:45 freqtrade:connection [WARN ] | Get "http://localhost:8080/api/v1/profit": dial tcp 127.0.0.1:8080: connect: connection refused
19:57:45 freqtrade:connection [WARN ] | Get "http://localhost:8080/api/v1/version": dial tcp 127.0.0.1:8080: connect: connection refused
19:57:45 freqtrade:connection [WARN ] | Get "http://localhost:8080/api/v1/show_config": dial tcp 127.0.0.1:8080: connect: connection refused
19:57:45 freqtrade:connection [WARN ] | Get "http://localhost:8080/api/v1/profit": dial tcp 127.0.0.1:8080: connect: connection refused
ftmetric:
    image: ghcr.io/kamontat/ftmetric:v4.3.0
    container_name: ftmetric
    restart: on-failure
    ports:
      - 8090:8090
    configs:
      - source: file1
        target: /fth/.env.docker
        mode: 444
    environment:
      - FTH_SERVER__PORT=8090
      - FTH_INTERNAL__LOG__LEVEL=4  
    depends_on:
      - freqtrade-eur
      - freqtrade-eth
    healthcheck:
      test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:8090/version"]
      interval: 1m
      timeout: 1s
      retries: 3
      start_period: 15s
/fth # ls -al
total 9040
drwxr-xr-x    1 root     root          4096 Jul 22 17:54 .
drwxr-xr-x    1 root     root          4096 Oct 21 19:54 ..
-rw-r--r--    1 1000     1000           506 Oct 21 19:46 .env.docker
drwxr-xr-x    2 root     root          4096 Jul 22 17:54 configs
-rwxr-xr-x    1 root     root       9240576 Jul 22 17:53 ftmetric
/fth # cat .env.docker 
FTH_CLUSTERS=1A,2A,3A

FTH_CLUSTER__1A__URL="http://freqtrade-eur:8080"
FTH_CLUSTER__1A__APIVER=v1
FTH_CLUSTER__1A__USERNAME="freqtradeEUR"
FTH_CLUSTER__1A__PASSWORD="SuperSecurePassword"

FTH_CLUSTER__2A__URL="http://freqtrade-eth:8080"
FTH_CLUSTER__2A__APIVER=v1
FTH_CLUSTER__2A__USERNAME="freqtradeETH"
FTH_CLUSTER__2A__PASSWORD="SuperSecurePassword"

FTH_CLUSTER__3A__URL="http://freqtrade-usdt:8080"
FTH_CLUSTER__3A__APIVER=v1
FTH_CLUSTER__3A__USERNAME="freqtradeETH"
FTH_CLUSTER__3A__PASSWORD="SuperSecurePassword"
/fth # 
/fth # wget http://freqtrade-eth:8080/api/v1/ping
Connecting to freqtrade-eth:8080 (172.25.0.5:8080)
saving to 'ping'
ping                 100% |***************************************************************************************|    17  0:00:00 ETA
'ping' saved
/fth # cat ping 
{"status":"pong"}
/fth # 

also i am not getting in prometheus the A1, A2, A3 shown from scraping...

[BUG]: v5.0.0-beta.12 seems not to gather from API

Bug report

Describe the bug

Prometheus does not scrape ftrqtrade related metrics

To Reproduce

Steps to reproduce the behavior:

  1. configure docker-compose file as following:

ftmetric1: image: ghcr.io/kamontat/ftmetric:v5.0.0-beta.12 container_name: ftmetric1 restart: on-failure ports: - 8091:8091 environment: - FTH_FREQTRADE__DB__ENABLED=false - FTH_SERVER__PORT=8091 - FTH_FREQTRADE__HTTP__APIVER=v1 - FTH_FREQTRADE__HTTP__URL=http://freqtrade1:8081 - FTH_FREQTRADE__HTTP__USERNAME=freqtrader - FTH_FREQTRADE__HTTP__PASSWORD=secret - FTH_FREQTRADE__HTTP__ENABLED=true command: --no-env-file --debug depends_on: - freqtrade1

Expected behavior

Result of freqtrade_mode non empty

Information

Try to complete information as much as possible.

  1. Desktop:
  • OS: Windows 11
  • WSL2 using docker
  • Browser firefox

Additional context

http://127.0.0.1:9090/targets shows status up
http://127.0.0.1:8091/metrics not showing metrics related to freqtrade
postman shows result for http://127.0.0.1:8081/api/v1/profit

[feature]: improve cache and warmup process

Feature request

We can create cache.Manager in metrics and register freqtrade apis in it and add looping method every cache that expired and fetch them again.

Is your feature request related to a problem?

A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]

Describe the solution you'd like

A clear and concise description of what you want to happen.

Additional context

Add any other context or screenshots about the feature request here.

[feature]: Allow multiple postgres database in one instance

Feature request

Is your feature request related to a problem?

But be nice to have the ability to specify the postgres database name.

Describe the solution you'd like

FTH_FREQTRADE__DB__URL={hostname}:5432/freqtrade1 <- allow to enter non standard appended "freqtrade" here

Additional context

I would like to host multiple bot db's on one postgres instance

[BUG]: hourly/daily/etc performance always empty

Bug report

Describe the bug

No matter how long the scraper runs, the performance metrics are always zero. This applies to all variants of freqtrade_perf_*.

To Reproduce

  • Start up with default config.
  • Periodically check prometheus metrics, they all return 0.

Expected behavior

Working metrics.

Information

5.0.0beta14

Additional context

I stepped in via VS Code. SchedulerPerformance::Build is called, but always with empty history. It seems like the performance values are never appended to the cache.

[BUG]: unexpected end of JSON input

i like to add a commons.json via:

 volumes:
      - "./fthelper:/fth/configs"

which results into:

panic: unexpected end of JSON input

goroutine 1 [running]:
main.main()
        /home/runner/work/fthelper/fthelper/metric/main.go:99 +0x8d7
panic: unexpected end of JSON input

[BUG]: No tag for linux/arm/v7

Hello. Please add tag for linux/arm/v7
When I pull (On Raspberry4)
docker pull ghcr.io/kamontat/ftmetric:stratch
stratch: Pulling from kamontat/ftmetric
no matching manifest for linux/arm/v7 in the manifest list entries

Please add tag for linux/arm/v7
Thank you

Either i don't understand how it is supposed to work, or a simple one cluster env setup does not work:

Either i don't understand how it is supposed to work, or a simple one cluster env setup does not work:

console args "--no-env-file --debug"

environment:
  - FTH_CLUSTERS=1A
  - FTH_CLUSTER__1A__DB__ENABLED=false      
  - FTH_CLUSTER__1A__HTTP__ENABLED=true
  - FTH_CLUSTER__1A__HTTP__URL="http://freqtrade1:8081"
  - FTH_CLUSTER__1A__HTTP__APIVER=v1
  - FTH_CLUSTER__1A__HTTP__USERNAME="freqtrader"
  - FTH_CLUSTER__1A__HTTP__PASSWORD="secret"
  - FTH_SERVER__PORT=8091

09:11:28 command:default [INFO ] | [with-cache] Connection cluster '1A' http - http://localhost:8080 ':' database - localhost:5432 (postgres) ':'
09:11:28 client:http:1A [DEBUG] | request: GET http://localhost:8080/api/v1/ping
09:11:28 cache:service [DEBUG] | creating 'http.total-call.1A' data
09:11:28 client:http:1A [DEBUG] | error: Get "http://localhost:8080/api/v1/ping": dial tcp 127.0.0.1:8080: connect: connection refused
09:11:28 cache:service [DEBUG] | creating 'http.failure-call.1A' data panic: found '2' errors (2)

  • Get "http://localhost:8080/api/v1/ping": dial tcp 127.0.0.1:8080: connect: connection refused
  • failed to connect to host=localhost user= database=freqtrade: dial error (dial tcp [::1]:5432: connect: cannot assign requested address) goroutine 1 [running]: main.defaultCommand(0xc000077720, 0x203000, 0xc00006bb40) /home/runner/work/fthelper/fthelper/metric/main.go:55 +0x81a github.com/kamontat/fthelper/shared/commandline/commands.(*Command).Start(0xc00006afc0, 0xc000077720, 0x2, 0xc00006bb40) /home/runner/work/fthelper/fthelper/shared/commandline/commands/command.go:27 +0x5a github.com/kamontat/fthelper/shared/commandline.(*cli).Start(0xc00002fa80, 0xc00001e070, 0x7, 0x7, 0xc0001ba708, 0xc0001c83f0) /home/runner/work/fthelper/fthelper/shared/commandline/cli.go:87 +0x9b2 main.main() /home/runner/work/fthelper/fthelper/metric/main.go:97 +0x477

09:13:29 map:merger [DEBUG] | merging key=log from -> map[level:4]
09:13:29 map:merger [DEBUG] | merging key=fs from -> map[env:map[fullpath:[/fth/.env.docker] mode:multiple type:auto]]
09:13:29 map:merger [DEBUG] | merging key=flag from -> map[noenv:true]
09:13:29 map:merger [DEBUG] | merging key=variables from -> map[current:/fth]
09:13:29 map:merger [DEBUG] | merging key=config from -> map[fullpath:[/fth/configs] mode:multiple type:auto]
09:13:29 map:merger [DEBUG] | merging key=clusters from -> []
09:13:29 map:merger [DEBUG] | merging key=level from 4 -> 2
09:13:29 map:merger [DEBUG] | merging key=fs from -> {"config":{"fullpath":["/fth/configs"],"mode":"multiple","type":"auto"},"env":{"fullpath":["/fth/.env.docker"],"mode":"multiple","type":"auto"}}
09:13:29 map:merger [DEBUG] | merging key=variables from -> {"current":"/fth"}
09:13:29 map:merger [DEBUG] | merging key=clusters from -> []
09:13:29 map:merger [DEBUG] | merging key=internal from -> map[flag:{"noenv":true} log:map[level:2] meta:{"buildby":"goreleaser","commit":"9a789b82aae38ffde2a14d38e7097ce22cb44499","date":"2021-08-24T15:03:23Z","name":"ftmetric","version":"5.0.0-beta.12"}]
09:13:29 config:builder [DEBUG] | base configuration is {"clusters":[""],"fs":{"config":{"fullpath":["/fth/configs"],"mode":"multiple","type":"auto"},"env":{"fullpath":["/fth/.env.docker"],"mode":"multiple","type":"auto"}},"internal":{"flag":{"noenv":true},"log":{"level":2},"meta":{"buildby":"goreleaser","commit":"9a789b82aae38ffde2a14d38e7097ce22cb44499","date":"2021-08-24T15:03:23Z","name":"ftmetric","version":"5.0.0-beta.12"}},"variables":{"current":"/fth"}}
09:13:29 fs:type:resolver [DEBUG] | mark /fth/configs as directory
09:13:29 config:builder [DEBUG] | loading config from wrapper of 'multiple': [/fth/configs (directory)]
09:13:29 map:merger [DEBUG] | merging key=server from -> map[metrics-path:/metrics port:8090]
09:13:29 map:merger [DEBUG] | merging key=warmup from -> map[enabled:true interval:30s]
09:13:29 map:merger [DEBUG] | merging key=clusters from -> []
09:13:29 map:merger [DEBUG] | merging key=freqtrade from -> map[cache:map[balance:3m count:1m locks:5m logs:1m performance:1m ping:1s profit:5m schedule_perf:1m show_config:1m stats:5m version:10m whitelist:15m] db:map[enabled:true name:freqtrade password: type:postgres url:localhost:5432 username:] http:map[apiver:v1 enabled:true password: query:map[logs:map[limit:100]] url:http://localhost:8080 username:]]
09:13:29 config:builder [DEBUG] | found some config in env
09:13:29 config:builder [DEBUG] | override 'cluster.1a.db.enabled' from '<**** [] -> 'f**** [bool] (env)
09:13:29 config:builder [DEBUG] | override 'cluster.1a.http.url' from '<**** [] -> '"http81" [string] (env)
09:13:29 config:builder [DEBUG] | override 'server.port' from '8
[float64] -> '8
[float64] (env)
09:13:29 config:builder [DEBUG] | override 'clusters' from '[
[[]interface {}] -> '[
[[]interface {}] (env)
09:13:29 config:builder [DEBUG] | override 'cluster.1a.http.apiver' from '<
[] -> 'v [string] (env)
09:13:29 config:builder [DEBUG] | override 'cluster.1a.http.username' from '<*** [] -> '"fr********" [string] (env)
09:13:29 config:builder [DEBUG] | override 'cluster.1a.http.password' from '<**** [] -> '"s*****" [string] (env)
09:13:29 config:builder [DEBUG] | override 'cluster.1a.http.enabled' from '<**** [] -> 't*** [bool] (env)
panic: found '2' errors (2)

  • Get "http://localhost:8080/api/v1/ping": dial tcp 127.0.0.1:8080: connect: connection refused
  • failed to connect to host=localhost user= database=freqtrade: dial error (dial tcp [::1]:5432: connect: cannot assign requested address)
    goroutine 1 [running]:
    main.defaultCommand(0xc0000b6c80, 0x203000, 0xc0000b8e80)
    /home/runner/work/fthelper/fthelper/metric/main.go:55 +0x81a
    github.com/kamontat/fthelper/shared/commandline/commands.(*Command).Start(0xc0000b8300, 0xc0000b6c80, 0x2, 0xc0000b8e80)
    /home/runner/work/fthelper/fthelper/shared/commandline/commands/command.go:27 +0x5a
    github.com/kamontat/fthelper/shared/commandline.(*cli).Start(0xc0000b0500, 0xc00001e070, 0x7, 0x7, 0xc00009a3c8, 0xc0000ae730)
    /home/runner/work/fthelper/fthelper/shared/commandline/cli.go:87 +0x9b2
    main.main()

Originally posted by @loewensteinph in #23 (comment)

[feature]: Daily stats and monthly stats

Hello,
Like we see in "daily" tab in freqUI, can we see daily stats here in this aswell?

either a table or a bar chart/graph?

i tried freqtrade_perf_daily but it says Empty query result in prom graph UI

and I am not able to make it work with grafana.

Would be great, if you can add a daily bar chart and monthly bar chart.

thanks :)

[BUG]: ftmetric with NFiNext Stategy error

Bug report

Describe the bug

Get error in the log files when starting the ftmetric container

Application:

  • Version: [e.g. 4.5.3]
20:56:55 freqtrade:connection:1A [WARN ] | Found error from freqtrade: Unexpected error input_arrays parameter missing required data key: close calling <bound method IStrategy._analyze_ticker_internal of <NostalgiaForInfinityNext.NostalgiaForInfinityNext object at 0x7f3adfdb4be0>>
Traceback (most recent call last):
  File "/freqtrade/freqtrade/strategy/strategy_wrapper.py", line 17, in wrapper
    return f(*args, **kwargs)
  File "/freqtrade/freqtrade/strategy/interface.py", line 417, in _analyze_ticker_internal
    dataframe = self.analyze_ticker(dataframe, metadata)
  File "/freqtrade/freqtrade/strategy/interface.py", line 396, in analyze_ticker
    dataframe = self.advise_indicators(dataframe, metadata)
  File "/freqtrade/freqtrade/strategy/interface.py", line 761, in advise_indicators
    return self.populate_indicators(dataframe, metadata)
  File "/freqtrade/user_data/strategies/NFiNext.py", line 2948, in populate_indicators
    informative_1h = self.informative_1h_indicators(dataframe, metadata)
  File "/freqtrade/user_data/strategies/NFiNext.py", line 2608, in informative_1h_indicators
    informative_1h['ema_12'] = ta.EMA(informative_1h, timeperiod=12)
  File "talib/_abstract.pxi", line 398, in talib._ta_lib.Function.__call__
  File "talib/_abstract.pxi", line 270, in talib._ta_lib.Function.set_function_args
  File "talib/_abstract.pxi", line 221, in talib._ta_lib.Function.set_input_arrays```

[BUG]: Docker Fthelper connection Refused

Bug report

Describe the bug

When Ft helper start a warning appear and all request report with "Connection Refused". All config i try fail to connect fthelper to freqtrade. No idea why he refuse to connect to the api.

`18:03:31 freqtrade:connection [WARN ] | Get "http://127.0.0.1:8081/api/v1/show_config": dial tcp 127.0.0.1:8081: connect: connection refused

//Fix the problem

 -FTH_FREQTRADE__URL=http://freqtrade1:8081

please show abs, pct coins by %

Hello,
currently freqtrade_pair_performance_profit_pct and freqtrade_pair_performance_profit_abs returns coins list alphabetically,
is it possible to show in descending order as we see in frequi Performance tab?

thanks,

Seems package is broken with latest freqtrade

Module

ftgenerator

Version

latest stable

What happened?

When using latest freqtrade 2022.6 (not so latest)

no. of finished trades is showing wrong number,
for example, in a dry-run, no. of closed trades are 83 but it is reporting -13 (yes, a negative number)

hope you can look into this.

thanks.

Relevant log output

No response

Docker compose configuration

No response

[BUG]: improve --debug to not output password / token / secret key

Bug report

Describe the bug

Sometime --debug will log password as well. This happen only for --debug because it force logging to be debug at every early stage of code. For --log-level 4 should not have this issue.

To Reproduce

Steps to reproduce the behavior:

  1. Go to '...'
  2. Click on '....'
  3. Scroll down to '....'
  4. See error

Expected behavior

A clear and concise description of what you expected to happen.

Screenshots

If applicable, add screenshots to help explain your problem.

Information

Try to complete information as much as possible.

  1. Desktop:
  • OS: [e.g. iOS]
  • Browser [e.g. chrome, safari]
  • Version [e.g. 22]
  1. Smartphone:
  • Device: [e.g. iPhone6]
  • OS: [e.g. iOS8.1]
  • Browser [e.g. stock browser, safari]
  • Version [e.g. 22]
  1. Application:
  • Version: [e.g. 1.0.0]

Additional context

(optional) Add any other context about the problem here.

[BUG]: Metric missing if you use same currency between crypto and fiat

any hints about this?

An error has occurred while serving metrics:

2 error(s) occurred:
* collected metric "freqtrade_perf_realized" { label:<name:"cluster" value:"1A" > label:<name:"stake" value:"EUR" > label:<name:"strategy" value:"BBRSIStrategy" > label:<name:"version" value:"docker-96f99699" > gauge:<value:1.63113677 > } was collected before with the same name and label values
* collected metric "freqtrade_perf_unrealized" { label:<name:"cluster" value:"1A" > label:<name:"stake" value:"EUR" > label:<name:"strategy" value:"BBRSIStrategy" > label:<name:"version" value:"docker-96f99699" > gauge:<value:1.63113677 > } was collected before with the same name and label values

and prometheus throws this error:

Endpoint State Labels Last Scrape Scrape Duration Error
http://ftmetric:8090/metrics DOWN instance="ftmetric:8090"job="ftmetric" 13.973s ago 97.952ms server returned HTTP status 500 Internal Server Error

[feature]: include used exchange in freqtrade status

(talking about the metrics part) Is it possible to show the exchange within the collected data like the strategy?
And another topic: can we have the output of show_config somewhere?
This would be great for "live-debugging" / using that data for further stuff...
Would like to give it a try to contribute here something, but you're so fast with releasing improvements - currently i'm using v5.3.0, will upgrade soon

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.