2022-05-25 22:48:59 +08:00
|
|
|
//go:generate ../../../tools/readme_config_includer/generator
|
2015-10-04 21:52:29 +08:00
|
|
|
package mqtt
|
|
|
|
|
|
|
|
|
|
import (
|
2022-07-27 23:36:57 +08:00
|
|
|
// Blank import to support go:embed compile directive
|
2022-05-25 22:48:59 +08:00
|
|
|
_ "embed"
|
2023-02-18 03:59:02 +08:00
|
|
|
"errors"
|
2015-10-04 21:52:29 +08:00
|
|
|
"fmt"
|
|
|
|
|
"sync"
|
2023-02-18 03:59:02 +08:00
|
|
|
"time"
|
2021-11-25 03:40:25 +08:00
|
|
|
|
2016-01-28 07:15:14 +08:00
|
|
|
"github.com/influxdata/telegraf"
|
2021-04-10 01:15:04 +08:00
|
|
|
"github.com/influxdata/telegraf/config"
|
2023-02-18 03:59:02 +08:00
|
|
|
"github.com/influxdata/telegraf/plugins/common/mqtt"
|
2016-01-21 02:57:35 +08:00
|
|
|
"github.com/influxdata/telegraf/plugins/outputs"
|
2016-02-11 06:50:07 +08:00
|
|
|
"github.com/influxdata/telegraf/plugins/serializers"
|
2015-10-04 21:52:29 +08:00
|
|
|
)
|
|
|
|
|
|
2022-05-25 22:48:59 +08:00
|
|
|
//go:embed sample.conf
|
|
|
|
|
var sampleConfig string
|
|
|
|
|
|
2015-10-04 21:52:29 +08:00
|
|
|
type MQTT struct {
|
2023-02-18 03:59:02 +08:00
|
|
|
TopicPrefix string `toml:"topic_prefix" deprecated:"1.25.0;use 'topic' instead"`
|
|
|
|
|
Topic string `toml:"topic"`
|
|
|
|
|
BatchMessage bool `toml:"batch"`
|
|
|
|
|
Log telegraf.Logger `toml:"-"`
|
|
|
|
|
mqtt.MqttConfig
|
|
|
|
|
|
|
|
|
|
client mqtt.Client
|
2016-02-11 06:50:07 +08:00
|
|
|
serializer serializers.Serializer
|
2023-01-18 02:45:45 +08:00
|
|
|
generator *TopicNameGenerator
|
2016-02-11 06:50:07 +08:00
|
|
|
|
2015-10-04 21:52:29 +08:00
|
|
|
sync.Mutex
|
|
|
|
|
}
|
|
|
|
|
|
2022-05-25 22:48:59 +08:00
|
|
|
func (*MQTT) SampleConfig() string {
|
|
|
|
|
return sampleConfig
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-18 02:45:45 +08:00
|
|
|
func (m *MQTT) Init() error {
|
2023-02-18 03:59:02 +08:00
|
|
|
if len(m.Servers) == 0 {
|
|
|
|
|
return errors.New("no servers specified")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if m.PersistentSession && m.ClientID == "" {
|
|
|
|
|
return errors.New("persistent_session requires client_id")
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if m.QoS > 2 || m.QoS < 0 {
|
|
|
|
|
return fmt.Errorf("qos value must be 0, 1, or 2: %d", m.QoS)
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-18 02:45:45 +08:00
|
|
|
var err error
|
|
|
|
|
m.generator, err = NewTopicNameGenerator(m.TopicPrefix, m.Topic)
|
2023-02-18 03:59:02 +08:00
|
|
|
return err
|
2023-01-18 02:45:45 +08:00
|
|
|
}
|
|
|
|
|
|
2015-10-04 21:52:29 +08:00
|
|
|
func (m *MQTT) Connect() error {
|
|
|
|
|
m.Lock()
|
|
|
|
|
defer m.Unlock()
|
|
|
|
|
|
2023-02-18 03:59:02 +08:00
|
|
|
client, err := mqtt.NewClient(&m.MqttConfig)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return err
|
2015-10-04 21:52:29 +08:00
|
|
|
}
|
2023-02-18 03:59:02 +08:00
|
|
|
m.client = client
|
2015-10-04 21:52:29 +08:00
|
|
|
|
2023-02-18 03:59:02 +08:00
|
|
|
_, err = m.client.Connect()
|
|
|
|
|
return err
|
2015-10-04 21:52:29 +08:00
|
|
|
}
|
|
|
|
|
|
2016-02-11 06:50:07 +08:00
|
|
|
func (m *MQTT) SetSerializer(serializer serializers.Serializer) {
|
|
|
|
|
m.serializer = serializer
|
|
|
|
|
}
|
|
|
|
|
|
2015-10-04 21:52:29 +08:00
|
|
|
func (m *MQTT) Close() error {
|
2022-07-27 23:36:57 +08:00
|
|
|
return m.client.Close()
|
2015-10-04 21:52:29 +08:00
|
|
|
}
|
|
|
|
|
|
2016-01-28 07:15:14 +08:00
|
|
|
func (m *MQTT) Write(metrics []telegraf.Metric) error {
|
2015-10-04 21:52:29 +08:00
|
|
|
m.Lock()
|
|
|
|
|
defer m.Unlock()
|
2016-01-28 07:15:14 +08:00
|
|
|
if len(metrics) == 0 {
|
2015-10-04 21:52:29 +08:00
|
|
|
return nil
|
|
|
|
|
}
|
2023-01-18 02:45:45 +08:00
|
|
|
|
2016-01-28 07:15:14 +08:00
|
|
|
hostname, ok := metrics[0].Tags()["host"]
|
2015-10-05 10:07:41 +08:00
|
|
|
if !ok {
|
|
|
|
|
hostname = ""
|
|
|
|
|
}
|
2018-05-19 09:55:02 +08:00
|
|
|
metricsmap := make(map[string][]telegraf.Metric)
|
2016-02-11 06:50:07 +08:00
|
|
|
for _, metric := range metrics {
|
2023-01-18 02:45:45 +08:00
|
|
|
topic, err := m.generator.Generate(hostname, metric)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return fmt.Errorf("topic name couldn't be generated due to error: %w", err)
|
2015-10-04 21:52:29 +08:00
|
|
|
}
|
|
|
|
|
|
2018-05-19 09:55:02 +08:00
|
|
|
if m.BatchMessage {
|
|
|
|
|
metricsmap[topic] = append(metricsmap[topic], metric)
|
|
|
|
|
} else {
|
|
|
|
|
buf, err := m.serializer.Serialize(metric)
|
|
|
|
|
if err != nil {
|
2021-11-25 03:40:25 +08:00
|
|
|
m.Log.Debugf("Could not serialize metric: %v", err)
|
2019-06-04 08:34:48 +08:00
|
|
|
continue
|
2018-05-19 09:55:02 +08:00
|
|
|
}
|
|
|
|
|
|
2022-07-27 23:36:57 +08:00
|
|
|
err = m.client.Publish(topic, buf)
|
2018-05-19 09:55:02 +08:00
|
|
|
if err != nil {
|
2021-11-25 03:40:25 +08:00
|
|
|
return fmt.Errorf("could not write to MQTT server, %s", err)
|
2018-05-19 09:55:02 +08:00
|
|
|
}
|
2016-02-11 06:50:07 +08:00
|
|
|
}
|
2018-05-19 09:55:02 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for key := range metricsmap {
|
|
|
|
|
buf, err := m.serializer.SerializeBatch(metricsmap[key])
|
2016-02-11 06:50:07 +08:00
|
|
|
|
2016-11-22 20:51:57 +08:00
|
|
|
if err != nil {
|
2018-05-19 09:55:02 +08:00
|
|
|
return err
|
|
|
|
|
}
|
2022-07-27 23:36:57 +08:00
|
|
|
err = m.client.Publish(key, buf)
|
|
|
|
|
if err != nil {
|
|
|
|
|
return fmt.Errorf("could not write to MQTT server, %s", err)
|
2015-10-04 21:52:29 +08:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func init() {
|
2016-01-28 05:21:36 +08:00
|
|
|
outputs.Add("mqtt", func() telegraf.Output {
|
2021-10-01 23:10:30 +08:00
|
|
|
return &MQTT{
|
2023-02-18 03:59:02 +08:00
|
|
|
MqttConfig: mqtt.MqttConfig{
|
|
|
|
|
KeepAlive: 30,
|
|
|
|
|
Timeout: config.Duration(5 * time.Second),
|
|
|
|
|
AutoReconnect: true,
|
|
|
|
|
},
|
2021-10-01 23:10:30 +08:00
|
|
|
}
|
2015-10-04 21:52:29 +08:00
|
|
|
})
|
|
|
|
|
}
|