1
// Copyright 2016 Canonical Ltd.
2
// Licensed under the AGPLv3, see LICENCE file for details.
7
"github.com/juju/errors"
8
"gopkg.in/juju/names.v2"
10
"github.com/juju/juju/api/base"
11
logfwdapi "github.com/juju/juju/api/logfwd"
12
"github.com/juju/juju/logfwd"
13
"github.com/juju/juju/logfwd/syslog"
16
// TrackingSinkArgs holds the args to OpenTrackingSender.
17
type TrackingSinkArgs struct {
18
// AllModels indicates that the tracker is handling all models.
21
// Config is the logging config that will be used.
22
Config *syslog.RawConfig
24
// Caller is the API caller that will be used.
27
// Name is the name given to the log sink.
30
// OpenSink is the function that opens the underlying log sink that
35
// OpenTrackingSink opens a log record sender to use with a worker.
36
// The sender also tracks records that were successfully sent.
37
func OpenTrackingSink(args TrackingSinkArgs) (*LogSink, error) {
38
sink, err := args.OpenSink(args.Config)
40
return nil, errors.Trace(err)
46
tracker: newLastSentTracker(args.Name, args.Caller),
51
type trackingSender struct {
53
tracker *lastSentTracker
57
// Send implements Sender.
58
func (s *trackingSender) Send(records []logfwd.Record) error {
59
if err := s.SendCloser.Send(records); err != nil {
60
return errors.Trace(err)
62
if err := s.tracker.setLastSent(s.allModels, records); err != nil {
63
return errors.Trace(err)
68
type lastSentTracker struct {
70
client *logfwdapi.LastSentClient
73
func newLastSentTracker(sink string, caller base.APICaller) *lastSentTracker {
74
client := logfwdapi.NewLastSentClient(func(name string) logfwdapi.FacadeCaller {
75
return base.NewFacadeCaller(caller, name)
77
return &lastSentTracker{
83
func (lst lastSentTracker) setLastSent(allModels bool, records []logfwd.Record) error {
84
// The records are received and sent in order, so we only need to
85
// call SetLastSent for the last record.
86
if len(records) == 0 {
89
rec := records[len(records)-1]
90
model := rec.Origin.ModelUUID
94
var modelTag names.ModelTag
96
if !names.IsValidModel(model) {
97
return errors.Errorf("bad model UUID %q", model)
99
modelTag = names.NewModelTag(model)
101
results, err := lst.client.SetLastSent([]logfwdapi.LastSentInfo{{
102
LastSentID: logfwdapi.LastSentID{
107
RecordTimestamp: rec.Timestamp,
110
return errors.Trace(err)
112
if err := results[0].Error; err != nil {
113
return errors.Trace(err)