diff --git a/dyn_stat.go b/dyn_stat.go
new file mode 100644
index 0000000000000000000000000000000000000000..f41fbcd19fb05cd6740d5a9aea615bf5f65871bd
--- /dev/null
+++ b/dyn_stat.go
@@ -0,0 +1,38 @@
+package main
+
+import (
+	"encoding/json"
+	"fmt"
+)
+
+type dynStat struct {
+	Name   string           `json:"name"`
+	Origin string           `json:"origin"`
+	Values map[string]int64 `json:"values"`
+}
+
+func newDynStatFromJSON(b []byte) (*dynStat, error) {
+	var pstat dynStat
+	err := json.Unmarshal(b, &pstat)
+	if err != nil {
+		return nil, fmt.Errorf("error decoding values stat `%v`: %v", string(b), err)
+	}
+	return &pstat, nil
+}
+
+func (i *dynStat) toPoints() []*point {
+	points := make([]*point, 0, len(i.Values))
+
+	for name, value := range i.Values {
+		points = append(points, &point{
+			Name:        fmt.Sprintf("dynstat_%s", i.Name),
+			Type:        counter,
+			Value:       value,
+			Description: fmt.Sprintf("dynamic statistic bucket %s", i.Name),
+			LabelName:   "counter",
+			LabelValue:  name,
+		})
+	}
+
+	return points
+}
diff --git a/dyn_stat_test.go b/dyn_stat_test.go
new file mode 100644
index 0000000000000000000000000000000000000000..8d7ff843aeab873032c718105b8a4725a2bfbebf
--- /dev/null
+++ b/dyn_stat_test.go
@@ -0,0 +1,115 @@
+package main
+
+import (
+	"reflect"
+	"testing"
+)
+
+func TestGetDynStat(t *testing.T) {
+	log := []byte(`{ "name": "global", "origin": "dynstats", "values": { "msg_per_host.ops_overflow": 1, "msg_per_host.new_metric_add": 3, "msg_per_host.no_metric": 0, "msg_per_host.metrics_purged": 0, "msg_per_host.ops_ignored": 0 } }`)
+	values := map[string]int64{
+		"msg_per_host.ops_overflow":   1,
+		"msg_per_host.new_metric_add": 3,
+		"msg_per_host.no_metric":      0,
+		"msg_per_host.metrics_purged": 0,
+		"msg_per_host.ops_ignored":    0,
+	}
+
+	if want, got := rsyslogDynStat, getStatType(log); want != got {
+		t.Errorf("detected pstat type should be %d but is %d", want, got)
+	}
+
+	pstat, err := newDynStatFromJSON(log)
+	if err != nil {
+		t.Fatalf("expected parsing dynamic stat not to fail, got: %v", err)
+	}
+
+	if want, got := "global", pstat.Name; want != got {
+		t.Errorf("invalid name, want '%s', got '%s'", want, got)
+	}
+
+	if want, got := values, pstat.Values; !reflect.DeepEqual(want, got) {
+		t.Errorf("unexpected values, want: %+v got: %+v", want, got)
+	}
+}
+
+func TestDynStatToPoints(t *testing.T) {
+	log := []byte(`{ "name": "global", "origin": "dynstats", "values": { "msg_per_host.ops_overflow": 1, "msg_per_host.new_metric_add": 3, "msg_per_host.no_metric": 0, "msg_per_host.metrics_purged": 0, "msg_per_host.ops_ignored": 0 } }`)
+	wants := map[string]point{
+		"msg_per_host.ops_overflow": point{
+			Name:        "dynstat_global",
+			Type:        counter,
+			Value:       1,
+			Description: "dynamic statistic bucket global",
+			LabelName:   "counter",
+			LabelValue:  "msg_per_host.ops_overflow",
+		},
+		"msg_per_host.new_metric_add": point{
+			Name:        "dynstat_global",
+			Type:        counter,
+			Value:       3,
+			Description: "dynamic statistic bucket global",
+			LabelName:   "counter",
+			LabelValue:  "msg_per_host.new_metric_add",
+		},
+		"msg_per_host.no_metric": point{
+			Name:        "dynstat_global",
+			Type:        counter,
+			Value:       0,
+			Description: "dynamic statistic bucket global",
+			LabelName:   "counter",
+			LabelValue:  "msg_per_host.no_metric",
+		},
+		"msg_per_host.metrics_purged": point{
+			Name:        "dynstat_global",
+			Type:        counter,
+			Value:       0,
+			Description: "dynamic statistic bucket global",
+			LabelName:   "counter",
+			LabelValue:  "msg_per_host.metrics_purged",
+		},
+		"msg_per_host.ops_ignored": point{
+			Name:        "dynstat_global",
+			Type:        counter,
+			Value:       0,
+			Description: "dynamic statistic bucket global",
+			LabelName:   "counter",
+			LabelValue:  "msg_per_host.ops_ignored",
+		},
+	}
+
+	seen := map[string]bool{}
+	for name, _ := range wants {
+		seen[name] = false
+	}
+
+	pstat, err := newDynStatFromJSON(log)
+	if err != nil {
+		t.Fatalf("expected parsing dyn stat not to fail, got: %v", err)
+	}
+
+	points := pstat.toPoints()
+	for _, got := range points {
+		key := got.LabelValue
+		want, ok := wants[key]
+		if !ok {
+			t.Errorf("unexpected point, got: %+v", got)
+			continue
+		}
+
+		if !reflect.DeepEqual(want, *got) {
+			t.Errorf("expected point to be %+v, got %+v", want, got)
+		}
+
+		if seen[key] {
+			t.Errorf("point seen multiple times: %+v", got)
+		}
+		seen[key] = true
+	}
+
+	for name, ok := range seen {
+		if !ok {
+			t.Errorf("expected to see point with key %s, but did not", name)
+		}
+	}
+}
diff --git a/exporter.go b/exporter.go
index 92acdc27644cd013754b49b36c1fe17eb8a43ff9..746c8c65580f4b1f4e0ad06ea673503b8a49e513 100644
--- a/exporter.go
+++ b/exporter.go
@@ -19,6 +19,7 @@ const (
 	rsyslogInput
 	rsyslogQueue
 	rsyslogResource
+	rsyslogDynStat
 )
 
 type rsyslogExporter struct {
@@ -84,6 +85,14 @@ func (re *rsyslogExporter) handleStatLine(rawbuf []byte) error {
 		for _, p := range r.toPoints() {
 			re.set(p)
 		}
+	case rsyslogDynStat:
+		s, err := newDynStatFromJSON(buf)
+		if err != nil {
+			return err
+		}
+		for _, p := range s.toPoints() {
+			re.set(p)
+		}
 
 	default:
 		return fmt.Errorf("unknown pstat type: %v", pstatType)
diff --git a/exporter_test.go b/exporter_test.go
index 99fedfc0238e1e74960d564b95f10b5fee6efd79..df2326e6102bbf541aa8c9afc389793df6b4d7ab 100644
--- a/exporter_test.go
+++ b/exporter_test.go
@@ -196,6 +196,40 @@ func TestHandleLineWithQueue(t *testing.T) {
 	testHelper(t, queueLog, tests)
 }
 
+func TestHandleLineWithGlobal(t *testing.T) {
+	tests := []*testUnit{
+		&testUnit{
+			Name:       "dynstat_global",
+			Val:        1,
+			LabelValue: "msg_per_host.ops_overflow",
+		},
+		&testUnit{
+			Name:       "dynstat_global",
+			Val:        3,
+			LabelValue: "msg_per_host.new_metric_add",
+		},
+		&testUnit{
+			Name:       "dynstat_global",
+			Val:        0,
+			LabelValue: "msg_per_host.no_metric",
+		},
+		&testUnit{
+			Name:       "dynstat_global",
+			Val:        0,
+			LabelValue: "msg_per_host.metrics_purged",
+		},
+		&testUnit{
+			Name:       "dynstat_global",
+			Val:        0,
+			LabelValue: "msg_per_host.ops_ignored",
+		},
+	}
+
+	log := []byte(`2018-01-18T09:39:12.763025+00:00 some-node.example.org rsyslogd-pstats: { "name": "global", "origin": "dynstats", "values": { "msg_per_host.ops_overflow": 1, "msg_per_host.new_metric_add": 3, "msg_per_host.no_metric": 0, "msg_per_host.metrics_purged": 0, "msg_per_host.ops_ignored": 0 } }`)
+
+	testHelper(t, log, tests)
+}
+
 func TestHandleUnknown(t *testing.T) {
 	unknownLog := []byte(`2017-08-30T08:10:04.786350+00:00 some-node.example.org rsyslogd-pstats: {"a":"b"}`)
 
diff --git a/utils.go b/utils.go
index 3180be8bbf658bbc4ef8623132e8b682b6ddac25..5130060c62c30bb4a93942959a7bf15bc1792270 100644
--- a/utils.go
+++ b/utils.go
@@ -12,6 +12,8 @@ func getStatType(buf []byte) rsyslogType {
 		return rsyslogQueue
 	} else if strings.Contains(line, "utime") {
 		return rsyslogResource
+	} else if strings.Contains(line, "dynstats") {
+		return rsyslogDynStat
 	}
 	return rsyslogUnknown
 }