hippo

package module
v1.2.0 Latest Latest
Warning

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

Go to latest
Published: May 21, 2019 License: MIT Imports: 16 Imported by: 2

README

Hippo Logo

Hippo

A Microservices Toolkit.

Hippo is a collection of well crafted go packages that help you build robust, reliable, maintainable microservices. It is not a full-fledged framework with lot of magic, predefined architecture, specific patterns and bullshit opinions so you will be the one behind the wheel.

It provides libraries to implement components for service discovery, async jobs, authentication, authorization, logging, caching, metrics, tracing, rate-limiting...etc which are essential requirements for running microservices in production.

Documentation

Installation:

go get -u github.com/clivern/hippo
import (
    "github.com/clivern/hippo"
)

Components:

HTTP Requests Component


httpClient := hippo.NewHTTPClient()

// Get Request
response, error := httpClient.Get(
    "https://httpbin.org/get",
    map[string]string{"url_arg_key": "url_arg_value"},
    map[string]string{"header_key": "header_value"},
)

// Delete Request
response, error := httpClient.Delete(
    "https://httpbin.org/delete",
    map[string]string{"url_arg_key": "url_arg_value"},
    map[string]string{"header_key": "header_value"},
)

// Post Request
response, error := httpClient.Post(
    "https://httpbin.org/post",
    `{"RequestBodyKey":"RequestBodyValue"}`,
    map[string]string{"url_arg_key": "url_arg_value"},
    map[string]string{"header_key": "header_value"},
)

// Put Request
response, error := httpClient.Put(
    "https://httpbin.org/put",
    `{"RequestBodyKey":"RequestBodyValue"}`,
    map[string]string{"url_arg_key": "url_arg_value"},
    map[string]string{"header_key": "header_value"},
)

// ....

statusCode := httpClient.GetStatusCode(response)
responseBody, error := httpClient.ToString(response)

Cache/Redis Component

driver := NewRedisDriver("localhost:6379", "password", 0)

// connect to redis server
ok, err := driver.Connect()
// ping check
ok, err = driver.Ping()

// set an item
ok, err = driver.Set("app_name", "Hippo", 0)
// check if exists
ok, err = driver.Exists("app_name")
// get value
value, err := driver.Get("app_name")
// delete an item
count, err := driver.Del("app_name")

// hash set
ok, err = driver.HSet("configs", "app_name", "Hippo")
// check if item on a hash
ok, err = driver.HExists("configs", "app_name")
// get item from a hash
value, err = driver.HGet("configs", "app_name")
// hash length
count, err = driver.HLen("configs")
// delete item from a hash
count, err = driver.HDel("configs", "app_name")
// clear the hash
count, err = driver.HTruncate("configs")

// Pub/Sub
driver.Publish("hippo", "Hello")
driver.Subscribe("hippo", func(message Message) error {
    // message.Channel
    // message.Payload
    return nil
})

Time Series/Graphite Component

import "time"


metric := hippo.NewMetric("hippo1.up", "23", time.Now().Unix()) // Type is hippo.Metric

metrics := NewMetrics("hippo2.up", "35", time.Now().Unix()) // type is []hippo.Metric
metrics = append(metrics, NewMetric("hippo2.down", "40", time.Now().Unix()))
metrics = append(metrics, NewMetric("hippo2.error", "70", time.Now().Unix()))

// NewGraphite(protocol string, host string, port int, prefix string)
// protocol can be tcp, udp or nop
// prefix is a metric prefix
graphite := hippo.NewGraphite("tcp", "127.0.0.1", 2003, "")
error := graphite.Connect()

if error == nil{
    // send one by one
    graphite.SendMetric(metric)

    // bulk send
    graphite.SendMetrics(metrics)
}

System Stats Component

// func NewSystemStats(enableCPU, enableMem, enableGC bool) *SystemStats {
stats := hippo.NewSystemStats(true, true, true)
stats.GetStats() // type map[string]uint64
// map[cpu.cgo_calls:0 cpu.goroutines:1 mem.alloc:0....]

Correlation ID Component

correlation := hippo.NewCorrelation()
correlation.UUIDv4()

Workers Pool Component

import "fmt"

tasks := []*hippo.Task{
    hippo.NewTask(func() (string, error) {
        fmt.Println("Task #1")
        return "Result 1", nil
    }),
    hippo.NewTask(func() (string, error) {
        fmt.Println("Task #2")
        return "Result 2", nil
    }),
    hippo.NewTask(func() (string, error) {
        fmt.Println("Task #3")
        return "Result 3", nil
    }),
}

// hippo.NewWorkersPool(tasks []*Task, concurrency int) *WorkersPool
p := hippo.NewWorkersPool(tasks, 2)
p.Run()

var numErrors int
for _, task := range p.Tasks {
    if task.Err != nil {
        fmt.Println(task.Err)
        numErrors++
    } else {
        fmt.Println(task.Result)
    }
    if numErrors >= 10 {
        fmt.Println("Too many errors.")
        break
    }
}

Health Checker Component

import "fmt"

healthChecker := hippo.NewHealthChecker()
healthChecker.AddCheck("ping_check", func() (bool, error){
    return true, nil
})
healthChecker.AddCheck("db_check", func() (bool, error){
    return false, fmt.Errorf("Database Down")
})
healthChecker.RunChecks()

fmt.Println(healthChecker.ChecksStatus())
// Output -> DOWN
fmt.Println(healthChecker.ChecksReport())
// Output -> [{"id":"ping_check","status":"UP","error":"","result":true},{"id":"db_check","status":"DOWN","error":"Database Down","result":false}] <nil>
import "fmt"

healthChecker := hippo.NewHealthChecker()

healthChecker.AddCheck("url_check", func() (bool, error){
    return hippo.HTTPCheck("httpbin_service", "https://httpbin.org/status/503", map[string]string{}, map[string]string{})
})
healthChecker.AddCheck("redis_check", func() (bool, error){
    return hippo.RedisCheck("redis_service", "localhost:6379", "", 0)
})
healthChecker.RunChecks()

fmt.Println(healthChecker.ChecksStatus())
// Outputs -> DOWN
fmt.Println(healthChecker.ChecksReport())
// Outputs -> [{"id":"url_check","status":"DOWN","error":"Service httpbin_service is unavailable","result":false},{"id":"redis_check","status":"DOWN","error":"Error while connecting redis_service: dial tcp [::1]:6379: connect: connection refused","result":false}] <nil>

API Rate Limiting


import "time"

// Create a limiter with a specific identifier(IP address or access token or username....etc)
// NewCallerLimiter(identifier string, eventsRate rate.Limit, tokenBurst int) *rate.Limiter
limiter := hippo.NewCallerLimiter("10.10.10.10", 100, 1)
if limiter.Allow() == false {
    // Don't allow access
} else {
    // Allow Access
}


// auto clean old clients (should run as background process)
// CleanupCallers(cleanAfter time.Duration)
go func(){
    for {
        time.Sleep(60 * time.Second)
        hippo.CleanupCallers(60)
    }
}()

Versioning

For transparency into our release cycle and in striving to maintain backward compatibility, Hippo is maintained under the Semantic Versioning guidelines and release process is predictable and business-friendly.

See the Releases section of our GitHub project for changelogs for each release version of Hippo. It contains summaries of the most noteworthy changes made in each release.

Bug tracker

If you have any suggestions, bug reports, or annoyances please report them to our issue tracker at https://github.com/clivern/hippo/issues

Security Issues

If you discover a security vulnerability within Hippo, please send an email to hello@clivern.com

Contributing

We are an open source, community-driven project so please feel free to join us. see the contributing guidelines for more details.

License

© 2019, Clivern. Released under MIT License.

Hippo is authored and maintained by @Clivern.

Documentation

Index

Constants

View Source
const (
	// ServiceUp const
	ServiceUp = "UP"
	// ServiceDown const
	ServiceDown = "DOWN"
	// ServiceUnknown const
	ServiceUnknown = "UNKNOWN"
)

Variables

This section is empty.

Functions

func CleanupCallers

func CleanupCallers(cleanAfter time.Duration)

CleanupCallers cleans old clients

func ExampleUUIDv4

func ExampleUUIDv4()

ExampleUUIDv4 example for UUIDv4 method

func HTTPCheck

func HTTPCheck(serviceName, URL string, parameters map[string]string, headers map[string]string) (bool, error)

HTTPCheck do HTTP health check

func NewCallerLimiter

func NewCallerLimiter(identifier string, eventsRate rate.Limit, tokenBurst int) *rate.Limiter

NewCallerLimiter create a new rate limiter with an identifier

func PkgName

func PkgName() string

PkgName returns the package name

func RedisCheck

func RedisCheck(serviceName string, addr string, password string, db int) (bool, error)

RedisCheck do a redis health check

Types

type Check

type Check struct {
	ID     string `json:"id"`
	Status string `json:"status"`
	Error  string `json:"error"`
	Result bool   `json:"result"`
	// contains filtered or unexported fields
}

Check struct

type Clock

type Clock struct {
}

Clock Type

func (*Clock) Now

func (c *Clock) Now() time.Time

Now get current time

func (*Clock) Sleep

func (c *Clock) Sleep(d time.Duration)

Sleep sleeps for a time

type ConsulConfig

type ConsulConfig struct {
	URL     string
	Version string
}

ConsulConfig struct

type ConsulKv

type ConsulKv struct {
	Config ConsulConfig
}

ConsulKv struct

func (*ConsulKv) Delete

func (c *ConsulKv) Delete(key string, parameters map[string]string) (string, error)

Delete deletes a kv

func (*ConsulKv) Read

func (c *ConsulKv) Read(key string, parameters map[string]string) (string, error)

Read gets a kv

func (*ConsulKv) Update

func (c *ConsulKv) Update(key string, value string, parameters map[string]string) (string, error)

Update update or create a kv

type ConsulStatus

type ConsulStatus struct {
	Config ConsulConfig
}

ConsulStatus struct

func (*ConsulStatus) GetRaftLeader

func (c *ConsulStatus) GetRaftLeader(parameters map[string]string) (string, error)

GetRaftLeader returns the Raft leader for the datacenter in which the agent is running

func (*ConsulStatus) ListRaftPeers

func (c *ConsulStatus) ListRaftPeers(parameters map[string]string) (string, error)

ListRaftPeers retrieves the Raft peers for the datacenter in which the the agent is running

type Correlation

type Correlation interface {
	UUIDv4() string
}

Correlation interface

func NewCorrelation

func NewCorrelation() Correlation

NewCorrelation creates an instance of correlation struct

type HTTPClient

type HTTPClient interface {
	Get(endpoint string, parameters map[string]string, headers map[string]string) (*http.Response, error)
	Post(endpoint string, data string, parameters map[string]string, headers map[string]string) (*http.Response, error)
	Put(endpoint string, data string, parameters map[string]string, headers map[string]string) (*http.Response, error)
	Delete(endpoint string, parameters map[string]string, headers map[string]string) (*http.Response, error)
	BuildParameters(endpoint string, parameters map[string]string) (string, error)
	ToString(response *http.Response) (string, error)
	BuildData(parameters map[string]string) string
	GetStatusCode(response *http.Response) int
}

HTTPClient interface

func NewHTTPClient

func NewHTTPClient() HTTPClient

NewHTTPClient creates an instance of http client

type Health

type Health struct {
	Status string
	Checks []*Check
}

Health struct

func NewHealthChecker

func NewHealthChecker() *Health

NewHealthChecker initializes a new health checker

func (*Health) AddCheck

func (h *Health) AddCheck(ID string, callable func() (bool, error))

AddCheck adds a new check

func (*Health) ChecksReport

func (h *Health) ChecksReport() (string, error)

ChecksReport get checks Status

func (*Health) ChecksStatus

func (h *Health) ChecksStatus() string

ChecksStatus get checks Status

func (*Health) Down

func (h *Health) Down() *Health

Down set the Status to Down

func (*Health) IsDown

func (h *Health) IsDown() bool

IsDown returns true if Status is Down

func (*Health) IsUnknown

func (h *Health) IsUnknown() bool

IsUnknown returns true if Status is Unknown

func (*Health) IsUp

func (h *Health) IsUp() bool

IsUp returns true if Status is Up

func (*Health) RunChecks

func (h *Health) RunChecks()

RunChecks runs all health checks

func (*Health) Unknown

func (h *Health) Unknown() *Health

Unknown set the Status to Unknown

func (*Health) Up

func (h *Health) Up() *Health

Up set the Status to Up

type Logger

type Logger struct {
	Driver string
}

Logger struct

func (*Logger) Info

func (l *Logger) Info(v ...interface{})

Info logs info message

func (*Logger) New

func (l *Logger) New() (*zap.Logger, error)

New returns a logger instance

type Message

type Message struct {
	Channel string
	Payload string
}

Message item

type Metric

type Metric struct {
	Name      string
	Value     string
	Timestamp int64
}

Metric struct

func NewMetric

func NewMetric(name, value string, timestamp int64) Metric

NewMetric creates a new metric

func NewMetrics

func NewMetrics(name, value string, timestamp int64) []Metric

NewMetrics creates a new metrics array

func (Metric) String

func (metric Metric) String() string

String transfer the metric to string

type ProcessLimiter

type ProcessLimiter interface {
	// Take should block to make sure that the RPS is met.
	Take() time.Time
}

ProcessLimiter interface

func NewProcessLimiter

func NewProcessLimiter(rate int) ProcessLimiter

NewProcessLimiter create a new process rate limiter

type Redis

type Redis struct {
	Client   *redis.Client
	Addr     string
	Password string
	DB       int
}

Redis driver

func NewRedisDriver

func NewRedisDriver(addr string, password string, db int) *Redis

NewRedisDriver create a new instance

func (*Redis) Connect

func (r *Redis) Connect() (bool, error)

Connect establish a redis connection

func (*Redis) Del

func (r *Redis) Del(key string) (int64, error)

Del deletes a record

func (*Redis) Exists

func (r *Redis) Exists(key string) (bool, error)

Exists deletes a record

func (*Redis) Get

func (r *Redis) Get(key string) (string, error)

Get gets a record value

func (*Redis) HDel

func (r *Redis) HDel(key, field string) (int64, error)

HDel deletes a hash record

func (*Redis) HExists

func (r *Redis) HExists(key, field string) (bool, error)

HExists checks if key exists on a hash

func (*Redis) HGet

func (r *Redis) HGet(key, field string) (string, error)

HGet gets a record from hash

func (*Redis) HLen

func (r *Redis) HLen(key string) (int64, error)

HLen count hash records

func (*Redis) HScan

func (r *Redis) HScan(key string, cursor uint64, match string, count int64) *redis.ScanCmd

HScan return an iterative obj for a hash

func (*Redis) HSet

func (r *Redis) HSet(key, field, value string) (bool, error)

HSet sets a record in hash

func (*Redis) HTruncate

func (r *Redis) HTruncate(key string) (int64, error)

HTruncate deletes a hash

func (*Redis) Ping

func (r *Redis) Ping() (bool, error)

Ping checks the redis connection

func (*Redis) Publish

func (r *Redis) Publish(channel string, message string) (bool, error)

Publish sends a message to channel

func (*Redis) Set

func (r *Redis) Set(key, value string, expiration time.Duration) (bool, error)

Set sets a record

func (*Redis) Subscribe

func (r *Redis) Subscribe(channel string, callback func(message Message) error) error

Subscribe listens to a channel

type SystemStats

type SystemStats struct {
	EnableCPU bool
	EnableMem bool
	EnableGC  bool
	StartTime time.Time
	Stats     map[string]uint64
}

SystemStats stuct

func NewSystemStats

func NewSystemStats(enableCPU, enableMem, enableGC bool) *SystemStats

NewSystemStats creates a new SystemStats

func (*SystemStats) Collect

func (s *SystemStats) Collect()

Collect collects enabled stats

func (*SystemStats) GetStats

func (s *SystemStats) GetStats() map[string]uint64

GetStats get stats list

type Task

type Task struct {
	Err    error
	Result string
	// contains filtered or unexported fields
}

Task struct

func NewTask

func NewTask(f func() (string, error)) *Task

NewTask initializes a new task based on a given work

func (*Task) Run

func (t *Task) Run(wg *sync.WaitGroup)

Run runs a Task

type TimeSeries

type TimeSeries interface {
	Connect() error
	Disconnect() error
	SendMetrics(metrics []Metric) error
	SendMetric(metric Metric) error
	IsNop() bool
}

TimeSeries interface

func NewGraphite

func NewGraphite(protocol string, host string, port int, prefix string) TimeSeries

NewGraphite create instance of graphite

type WorkersPool

type WorkersPool struct {
	Tasks []*Task
	// contains filtered or unexported fields
}

WorkersPool struct

func NewWorkersPool

func NewWorkersPool(tasks []*Task, concurrency int) *WorkersPool

NewWorkersPool initializes a new pool with the given tasks

func (*WorkersPool) Run

func (w *WorkersPool) Run()

Run runs all work within the pool and blocks until it's finished.

Jump to

Keyboard shortcuts

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