progressio

package module
v0.0.0-...-f8b5847 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Dec 8, 2019 License: MIT Imports: 5 Imported by: 0

README

progressio

GoDoc

Library to get progress feedback from io.Reader and io.Writer objects

To install, run go get github.com/bartmeuris/progressio

About

This package was created since most progress packages out-there seem to directly want to output stuff to a console mixing UI and work logic, work in a non-Go way (callback functions), or can only be used for specific scenario's like file downloads from the web.

This package provides wrappers around standard io.Reader and io.Writer objects which send back a progressio.Progress struct over a channel, so anything that uses standard io.Reader/io.Writer objects can give you progress feedback. It attempts to do all the heavy lifting for you:

  • updates are throttled to 1 per 100ms (10 per second)
  • Precalculates things (if possible) like:
    • Speed in bytes/sec of the last few operations
    • Average speed in bytes/sec since the start of the operation
    • Remaining time
    • Percentage

Some of these statistics are not available if the size was not specified up front.

Progress object

Layout
type Progress struct {
    Transferred int64         // Transferred data in bytes
    TotalSize   int64         // Total size of the transfer in bytes. <= 0 if size is unknown.
    Percent     float64       // If the size is known, the progress of the transfer in %
    SpeedAvg    int64         // Bytes/sec average over the entire transfer
    Speed       int64         // Bytes/sec of the last few reads/writes
    Remaining   time.Duration // Estimated time remaining, only available if the size is known.
    StartTime   time.Time     // When the transfer was started
    StopTime    time.Time     // only specified when the transfer is completed: when the transfer was stopped
}

Functions

The progressio.Progress object has at the moment only one function, the String() function to return the string representation of the object.

Example

import (
  "io"
  "github.com/bartmeuris/progressio"
)

// io.Copy wrapper to specify the size and show copy progress.
func copyProgress(w io.Writer, r io.Reader, size int64) (written int64, err error) {
  
  // Wrap your io.Writer:
  pw, ch := progressio.NewProgressWriter(w, size)
  defer pw.Close()
  
  // Launch a Go-Routine reading from the progress channel
  go func() {
    for p := range ch {
      fmt.Printf("\rProgress: %s", p.String())
    }
    fmt.Printf("\nDone\n")
  }
  
  // Copy the data from the reader to the new writer
  return io.Copy(pw, r)
}

TODO

  • Add tests
  • Clean up documentation
  • Document byte/duration formatters
  • Extract byte/duration formatters and place in separate library (?)

Documentation

Overview

Package progressio contains io.Reader and io.Writer wrappers to easily get progress feedback, including speed/sec, average speed, %, time remaining, size, transferred size, ... over a channel in a progressio.Progress object.

Important note is that the returned object implements the io.Closer interface and you have to close the progressio.ProgressReader and progressio.ProgressWriter objects in order to clean everything up.

Usage is pretty simple:

preader, pchan := progressio.NewProgressReader(myreader, -1)
defer preader.Close()
go func() {
	for p := range pchan {
		fmt.Printf("Progress: %s\n", p.String())
	}
}
// read from your new reader object
io.Copy(mywriter, preader)

A helper function is available that opens a file, determines it's size, and wraps it's os.File io.Reader object:

if pr, pc, err := progressio.NewProgressFileReader(myfile); err != nil {
	return err
} else {
	defer pr.Close()
	go func() {
		for p := range pc{
			fmt.Printf("Progress: %s\n", p.String())
		}
	}
	// read from your new reader object
	io.Copy(mywriter, pr)
}

A wrapper for an io.WriterCloser is available too, but no helper function is available to write to an os.File since the target size is not known. Usually, wrapping the io.Writer is more accurate, since writing potentially takes up more time and happens last. Useage is similar to wrapping the io.Reader:

pwriter, pchan := progressio.NewProgressWriter(mywriter, -1)
defer pwriter.Close()
go func() {
	for p := range pchan {
		fmt.Printf("Progress: %s\n", p.String())
	}
}
// write to your new writer object
io.Copy(pwriter, myreader)

Note that you can also implement your own formatting. See the String() function implementation or consult the Progress struct layout and documentation

Index

Constants

View Source
const (
	Byte int64 = 1 // Byte is the representation of a single byte

	MetricMultiplier = 1000                        // Metric uses 1 10^3 multiplier
	KiloByte         = Byte * MetricMultiplier     // Metric unit "KiloByte" constant
	MegaByte         = KiloByte * MetricMultiplier // Metric unit MegaByte constant
	GigaByte         = MegaByte * MetricMultiplier // Metric unit GigaByte constant
	TeraByte         = GigaByte * MetricMultiplier // Metric unit TerraByte constant
	PetaByte         = TeraByte * MetricMultiplier // Metric unit PetaByte constant

	IECMultiplier = 1024                     // IEC Standard multiplier, 1024 based
	KibiByte      = Byte * IECMultiplier     // IEC standard unit KibiByte constant
	MebiByte      = KibiByte * IECMultiplier // IEC standard unit MebiByte constant
	GibiByte      = MebiByte * IECMultiplier // IEC standard unit GibiByte constant
	TebiByte      = GibiByte * IECMultiplier // IEC standard unit TebiByte constant
	PebiByte      = TebiByte * IECMultiplier // IEC standard unit PebiByte constant

	JEDECKiloByte = KibiByte // JEDEC uses IEC multipliers, but Metric names, JEDEC KiloByte constant
	JEDECMegaByte = MebiByte // JEDEC uses IEC multipliers, but Metric names, JEDEC MegaByte constant
	JEDECGigaByte = GibiByte // JEDEC uses IEC multipliers, but Metric names, JEDEC GigaByte constant
)

Various constants related to the units

View Source
const UpdateFreq = 100 * time.Millisecond

Frequency of the updates over the channels

Variables

View Source
var IEC = SizeSystem{
	Name:       "IEC",
	MultiPlier: IECMultiplier,
	Names:      _IECNames,
	Shorts:     _IECShorts,
}

IEC is a SizeSystem instance representing the IEC standard

View Source
var JEDEC = SizeSystem{
	Name:       "JEDEC",
	MultiPlier: IECMultiplier,
	Names:      _JEDECNames,
	Shorts:     _JEDECShorts,
}

JEDEC is a SizeSystem instance representing the JEDEC standard

View Source
var Metric = SizeSystem{
	Name:       "metric",
	MultiPlier: MetricMultiplier,
	Names:      _MetricNames,
	Shorts:     _MetricShorts,
}

Metric is a SizeSystem instance representing the metric system

Functions

func FormatDuration

func FormatDuration(dur time.Duration) string

FormatDuration returns the string representation of the specified time.Duration, in the (if applicable) amount of weeks, days, hours, minutes and seconds it represents

func FormatSeconds

func FormatSeconds(seconds int64) string

FormatSeconds returns a string representing the (if applicable) amount of weeks, days, hours, minutes and seconds the amount of seconds it is passed as a parameter.

func FormatSize

func FormatSize(ss SizeSystem, size int64, short bool) string

FormatSize formats a number of bytes using the given unit standard system. If the 'short' flag is set to true, it uses the shortened names.

Types

type Progress

type Progress struct {
	Transferred int64         // Transferred data in bytes
	TotalSize   int64         // Total size of the transfer in bytes. <= 0 if size is unknown.
	Percent     float64       // If the size is known, the progress of the transfer in %
	SpeedAvg    int64         // Bytes/sec average over the entire transfer
	Speed       int64         // Bytes/sec of the last few reads/writes
	Remaining   time.Duration // Estimated time remaining, only available if the size is known.
	StartTime   time.Time     // When the transfer was started
	StopTime    time.Time     // only specified when the transfer is completed: when the transfer was stopped
}

Progress is the object sent back over the progress channel.

func (*Progress) String

func (p *Progress) String() string

String returns a string representation of the progress. It takes into account if the size was known, and only tries to display relevant data.

type ProgressReader

type ProgressReader struct {
	// contains filtered or unexported fields
}

ProgressReader is a struct representing an io.ReaderCloser, which sends back progress feedback over a channel

func NewProgressFileReader

func NewProgressFileReader(file string) (*ProgressReader, <-chan Progress, error)

NewProgressFileReader creates a new ProgressReader based on a file. It teturns a ProgressReader object and a channel on success, or an error on failure.

func NewProgressReader

func NewProgressReader(r io.Reader, size int64) (*ProgressReader, <-chan Progress)

NewProgressReader creates a new ProgressReader object based on the io.Reader and the size you specified. Specify a size <= 0 if you don't know the size.

func (*ProgressReader) Close

func (p *ProgressReader) Close() (err error)

Close wraps the io.ReaderCloser Close function to clean up everything. ProgressReader objects should always be closed to make sure everything is cleaned up.

func (*ProgressReader) Read

func (p *ProgressReader) Read(b []byte) (n int, err error)

Read wraps the io.Reader Read function to also update the progress.

type ProgressWriter

type ProgressWriter struct {
	// contains filtered or unexported fields
}

ProgressWriter is a struct representing an io.WriterCloser, which sends back progress feedback over a channel

func NewProgressWriter

func NewProgressWriter(w io.Writer, size int64) (*ProgressWriter, <-chan Progress)

NewProgressWriter creates a new ProgressWriter object based on the io.Writer and the size you specified. Specify a size <= 0 if you don't know the size.

func (*ProgressWriter) Close

func (p *ProgressWriter) Close() (err error)

Close wraps the io.WriterCloser Close function to clean up everything. ProgressWriter objects should always be closed to make sure everything is cleaned up.

func (*ProgressWriter) Write

func (p *ProgressWriter) Write(b []byte) (n int, err error)

Write wraps the io.Writer Write function to also update the progress.

type SecondFormatter

type SecondFormatter int64

SecondFormatter represents a duration in seconds

func (SecondFormatter) Days

func (s SecondFormatter) Days() int64

Days returns the amount of days of a partial week represented by the SecondFormatter instance Minimum value: 0, Maximum Value: 6

func (SecondFormatter) Hours

func (s SecondFormatter) Hours() int64

Hours returns the amount of hours of the last partial day represented by the SecondFormatter instance Minumum value: 0, Maximum value: 23

func (SecondFormatter) Minutes

func (s SecondFormatter) Minutes() int64

Minutes returns the amount of minutes of the last partial hour represented by the SecondFormatter instance Minumum value: 0, Maximum value: 59

func (SecondFormatter) Seconds

func (s SecondFormatter) Seconds() int64

Seconds returns the amount of seconds of the last partial minute represented by the SecondFormatter instance Minumum value: 0, Maximum value: 59

func (SecondFormatter) String

func (s SecondFormatter) String() string

String returns the string representation of the SecondFormatter instance, specifying (if applicable): the amount of weeks, days, hours, minutes and seconds it represents

func (SecondFormatter) Weeks

func (s SecondFormatter) Weeks() int64

Weeks returns the amount of whole weeks represented by the SecondFormatter instance Minimum value: 0

type SizeSystem

type SizeSystem struct {
	Name       string   // The name of the unit standard
	MultiPlier int64    // The multiplier used by the unit standard
	Names      []string // The names used by the unit standard
	Shorts     []string // The shortened names used by the unit standard
}

SizeSystem is a structure representing a unit standard

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL