Extract node statistics from docker

Hello,

I am considering the installation of a device from this link into my home setup, which is based on an old 1-gen HP Microserver. My goal is to display various statistics.

Could anyone provide guidance on the commands needed to retrieve the following data from a Docker container from a storage node to stdout?

  • Current space usage
  • Available free space
  • Current month’s ingress and egress
  • Current month’s estimations
  • Hold
  • All-time earnings data

Any assistance or suggestions would be greatly appreciated.

This can get you started

    satellites=$(/usr/bin/docker exec storagenode wget -qO - localhost:14002/api/sno/satellites 2>/dev/null)
    dashboard=$(/usr/bin/docker exec storagenode wget -qO - localhost:14002/api/sno/ 2>/dev/null)
    bandwidthSummary=$(jq -r .bandwidthSummary <<<${satellites})
    egressSummary=$(echo ${satellites} | jq -r '.bandwidthDaily[].egress' |
        jq -n 'reduce (inputs | to_entries[]) as {$key,$value} ({}; .[$key] += $value)' |
        jq -r .[] | paste -s -d+ - | bc)
    egressDaily=$(echo ${satellites} | jq -r .bandwidthDaily[-1].egress[] | paste -s -d+ - | bc)
    ingressDaily=$(echo ${satellites} | jq -r .bandwidthDaily[-1].ingress[] | paste -s -d+ - | bc)
    diskSpace=$(jq -r .diskSpace.used <<<${dashboard})
    diskSpaceAvailable=$(jq -r .diskSpace.available <<<${dashboard})
    est=$(/usr/bin/docker exec -i storagenode wget -qO - localhost:14002/api/sno/estimated-payout 2>/dev/null | jq -r .currentMonthExpectations | awk '{printf ("%'\''d\n", $0/100)}')

2 Likes

Here is the daemon for updating the CFA631 screen via lcdproc with the current month bandwidth and estimations.

#!/usr/bin/python3

import pylcddc.client as client
import pylcddc.widgets as widgets
import pylcddc.screen as screen
import requests,json,time,logging
from systemd import journal

# Set up logging to the systemd journal
logger = logging.getLogger(__name__)
logger.addHandler(journal.JournalHandler())
logger.setLevel(logging.INFO)


def get_data():
    # Direct API calls to get the required data
    #satellites = requests.get('http://localhost:14002/api/sno/satellites').json()
    dashboard = requests.get('http://localhost:14002/api/sno/').json()
    estimated_payout = requests.get('http://localhost:14002/api/sno/estimated-payout').json()

    # Extract version_info directly from the dashboard call
    version_info = dashboard['version']

    # Parse the data to get bandwidth summary (Traffic) in bytes and current month expectations (EST) in dollars
    #bandwidth_summary_bytes = satellites['bandwidthSummary']
    bandwidth_summary_bytes = dashboard['bandwidth']['used']
    est_dollars = estimated_payout['currentMonthExpectations'] / 100  # Adjusting to get a dollar value

    # Convert traffic to a human-readable format
    units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB']
    size = bandwidth_summary_bytes
    for unit in units:
        if size < 1024:
            traffic = f"{size:.2f} {unit}"
            break
        size /= 1024
    else:
        traffic = f"{size:.2f} {units[-1]}"  # Handle extremely large numbers

    # Format EST to display as currency with 2 decimal places
    est = f"${est_dollars:.2f}"

    return version_info, traffic, est

def update_display(c, version_info, traffic, est):
    # Use version_info as the title for the screen
    title_widget = widgets.Title('title_widget', f"Storj {version_info}")
    # Calculate the total length of the traffic and EST strings
    total_length = len(traffic) + len(est)
    # Calculate the number of spaces needed to fill up the line to ensure EST is right-aligned
    spaces_needed = 20 - total_length
    # Ensure there is at least one space between the values if they are too long
    if spaces_needed < 1:
        spaces_needed = 1
    # Combine traffic and EST into a single string with dynamic spacing
    combined_info = f"{traffic}{' ' * spaces_needed}{est}"
    # Create a single widget for the combined information
    info_widget = widgets.String('info_widget', 1, 2, combined_info)  # Assuming the title takes up the first line
    main_scr = screen.Screen('main', [title_widget, info_widget])
    try:
        # Attempt to update the screen in the client
        c.update_screens([main_scr]) 
    except Exception as e:
        print(f"Error updating display: {e}")

if __name__ == '__main__':
    # Initialize LCD client
    c = client.Client('localhost', 13666)
    title_widget = widgets.Title('title_widget', 'Init')
    info_widget = widgets.String('info_widget', 1, 2, 'Loading...') 
    # Create a screen instance with the title and combined info widgets
    main_scr = screen.Screen('main', [title_widget, info_widget])
    c.add_screen(main_scr)
    
    try:
        while True:
            # Fetch data including Traffic, EST values, and Version for title
            version_info, traffic, est = get_data()

            # Log the current time, traffic, and EST to the journal
            current_time = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime())
            logger.info(f'Current time: {current_time}, Traffic: {traffic}, EST: {est}')

            # Update the display with the fetched data
            update_display(c, version_info, traffic, est)

            # Wait for 15 seconds before the next update
            time.sleep(15)
    except KeyboardInterrupt:
        logger.info("Exiting...")
    finally:
        c.close()

3 Likes