= Hawkular-Client for Go
Michael Burman
2016-05-09
:toc: macro
:toc-title:

ifdef::env-github[]
image:https://travis-ci.org/hawkular/hawkular-client-go.svg?branch=master["Build Status", link="https://travis-ci.org/hawkular/hawkular-client-go"]
endif::[]

toc::[]

== Introduction
This client provides abstractions to use the link:http://www.hawkular.org[Hawkular] REST-endpoints. At this point, only the metrics interface is supported (standalone or part of the distribution). Real world usage can be found for example from the link:http://kubernetes.io/[Kubernetes]' monitoring project, link:https://github.com/kubernetes/heapster[Heapster] and this client is bundled with the link:https://www.openshift.org/[Openshift] to provide metrics functionality from link:https://github.com/hawkular/hawkular-metrics[Hawkular-Metrics]. 

For further information on available functionality, see the link:http://www.hawkular.org/docs/components/metrics/index.html[documentation of Hawkular-Metrics].

=== License and copyright

....
   Copyright 2015-2016 Red Hat, Inc. and/or its affiliates
   and other contributors.

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
....

== Usage

=== Installation

To install the package, one can use the go command of `go get github.com/hawkular/hawkular-client-go`.

=== Basic usage

For examples of usage, see the link:https://github.com/hawkular/hawkular-client-go/blob/master/metrics/client_test.go[client_test.go].

==== Initialization

To create new instance of Hawkular, use the function NewHawkularClient and provide it with the struct Parameters

[source,go]
----
p := Parameters{Tenant: "default", Url: "http://localhost:8080"}
h := NewHawkularClient(p)
----

==== Creating and modifying metric definitions

To create new metric definitions, we need the MetricDefinition struct. The required information is Id and Type, but you can also add tags at the same time. In this example we create a metric called `doc.gauge.1` and set some tags to it. You can later alter the tags by using the methods `UpdateTags` and `DeleteTags`. The `Create` function returns two values, first a boolean that indicates if the creation succeeded (it will return false if there's duplicate `id` already) and also any potential connection or other errors.

[source,go]
----
tags := make(map[string]string)
tags["env"] = "documentation-project"

md_tags := MetricDefinition{Id: "doc.gauge.1", Tags: tags, Type: Gauge}
ok, err = c.Create(md_tags)
----

Fetching the definitions and tags introduces us to the principal concept around the client, which is compositional functions. We can alter the behavior of all the commands in the go-client by giving as input some modifier functions. Fetching the definitions happens with the function `Definitions` and as parameters we can give it some filters by including them inside the `Filters` function. For example to get all the Gauge definitions with given tags filter, we would do the following:

[source,go]
----
mdq, err := c.Definitions(Filters(TypeFilter(Gauge), TagsFilter(tags)))
----

==== Writing datapoints

Datapoints are written to the server inside the MetricHeader. You need to create Datapoint struct and set the time and value and embed that datapoint inside a MetricHeader struct. You can write multiple datapoints to a multiple metric ids in a single call to Write().

If the Write() happens to fail with some temporary reason (such as network issue), you can always resend the same request - old values are simply overwritten. 

[source,go]
----
dp := Datapoint{Value: 1.45, Timestamp: time.Now()}

header := MetricHeader{
      ID:   "doc.gauge.1",
      Data: []Datapoint{dp},
      Type: Gauge,
}
err := c.Write([]MetricHeader{header})
----

For performance reasons, it is recommended to write multiple metrics in one call.

==== Reading datapoints

Reading datapoints has two approaches, you can either request raw metrics and datapoints that you've stored on the server or you can request aggregates / downsampled values. ReadRaw() returns the same datatypes as what was used when writing to the server:

[source,go]
----
metric, err := c.ReadRaw(Gauge, "doc.gauge.1")
----

`metric` should now be equal to what we sent in the previous chapter. We can change the order of returned metrics by giving `OrderFilter` function inside the Filters function as parameter to the ReadRaw. Default is ascending.

To request aggregated view of the stored metrics, we can use the `ReadBuckets()` method. The returned struct is `Bucketpoint`. In the following example we'll request a single bucket of all the data, data was searched from all the metrics that have `env` tag with value `unittest` and we're interested in calculated percentiles of values `90%` and `99%`.

[source,go]
----
tags := make(map[string]string)
tags["env"] = "unittest"

bp, err := c.ReadBuckets(Gauge, Filters(TagsFilter(tags), BucketsFilter(1), PercentilesFilter([]float64{90.0, 99.0})))
----

=== Advanced usage

link:https://godoc.org/github.com/hawkular/hawkular-client-go/metrics[GoDoc]

==== Extending feature set
Client usage is based on the compositional nirvana, overloading the functions with more functions. All the functions are built on top of the Send(), which is accepting functions that are based on the Modifier type.

[source,go]
.Base function used to build features
----
type Modifier func(*http.Request) error
----

INFO: Don't forget to check `Filter` type and `Endpoint` type as well, which may be better startpoint for URL modifiers.

