repo_description: Like Prometheus, but for logs.
repo_topics: cloudnative grafana hacktoberfest logging loki prometheus
code: package main
  
  import (
  	"bytes"
  	"encoding/json"
  	"sort"
  	"strconv"
  )
  
  type Label struct {
  	Name, Value string
  }
  
  type Labels []Label
  
  func (ls Labels) Len() int           { return len(ls) }
  func (ls Labels) Swap(i, j int)      { ls[i], ls[j] = ls[j], ls[i] }
  func (ls Labels) Less(i, j int) bool { return ls[i].Name < ls[j].Name }
  
  func (ls Labels) String() string {
  	var b bytes.Buffer
  
  	b.WriteByte('{')
  	for i, l := range ls {
  		if i > 0 {
  			b.WriteByte(',')
  			b.WriteByte(' ')
  		}
  		b.WriteString(l.Name)
  		b.WriteByte('=')
  		b.WriteString(strconv.Quote(l.Value))
  	}
  	b.WriteByte('}')
  
  	return b.String()
  }
  
  // FromMap returns new sorted Labels from the given map.
  func FromMap(m map[string]string) Labels {
  	l := make([]Label, 0, len(m))
  	for k, v := range m {
  		l = append(l, Label{Name: k, Value: v})
  	}
  	return New(l...)
  }
  
  // New returns a sorted Labels from the given labels.
  // The caller has to guarantee that all label names are unique.
  func New(ls ...Label) Labels {
  	set := make(Labels, 0, len(ls))
  	for _, l := range ls {
  		set = append(set, l)
  	}
  	sort.Sort(set)
  
  	return set
  }
  
  // Map returns a string map of the labels.
  func (ls Labels) Map() map[string]string {
  	m := make(map[string]string, len(ls))
  	for _, l := range ls {
  		m[l.Name] = l.Value
  	}
  	return m
  }
  
  // MarshalJSON implements json.Marshaler.
  func (ls Labels) MarshalJSON() ([]byte, error) {
  	return json.Marshal(ls.Map())
  }
  
  // UnmarshalJSON implements json.Unmarshaler.
  func (ls *Labels) UnmarshalJSON(b []byte) error {
  	var m map[string]string
  
  	if err := json.Unmarshal(b, &m); err != nil {
  		return err
  	}
  
  	*ls = FromMap(m)
  	return nil
  }
  