Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ require (
github.com/santhosh-tekuri/jsonschema/v5 v5.3.1
github.com/seancfoley/ipaddress-go v1.7.1
github.com/sensu/sensu-go/api/core/v2 v2.16.0
github.com/shirou/gopsutil/v4 v4.25.5
github.com/shirou/gopsutil/v4 v4.25.12
github.com/showwin/speedtest-go v1.7.10
github.com/signalfx/golib/v3 v3.3.54
github.com/sijms/go-ora/v2 v2.9.0
Expand All @@ -198,7 +198,7 @@ require (
github.com/snowflakedb/gosnowflake v1.14.1
github.com/srebhan/cborquery v1.0.4
github.com/srebhan/protobufquery v1.0.4
github.com/stretchr/testify v1.10.0
github.com/stretchr/testify v1.11.1
github.com/tbrandon/mbserver v0.0.0-20170611213546-993e1772cc62
github.com/tdrn-org/go-hue v0.3.0
github.com/testcontainers/testcontainers-go v0.37.0
Expand Down Expand Up @@ -231,7 +231,7 @@ require (
golang.org/x/net v0.41.0
golang.org/x/oauth2 v0.30.0
golang.org/x/sync v0.15.0
golang.org/x/sys v0.33.0
golang.org/x/sys v0.38.0
golang.org/x/term v0.32.0
golang.org/x/text v0.26.0
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20211230205640-daad0b7ba671
Expand Down Expand Up @@ -362,7 +362,7 @@ require (
github.com/eapache/go-resiliency v1.7.0 // indirect
github.com/eapache/go-xerial-snappy v0.0.0-20230731223053-c322873962e3 // indirect
github.com/eapache/queue v1.1.0 // indirect
github.com/ebitengine/purego v0.8.4 // indirect
github.com/ebitengine/purego v0.9.1 // indirect
github.com/echlebek/timeproxy v1.0.0 // indirect
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
github.com/envoyproxy/go-control-plane/envoy v1.32.4 // indirect
Expand Down Expand Up @@ -524,8 +524,8 @@ require (
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.1 // indirect
github.com/tidwall/tinylru v1.2.1 // indirect
github.com/tklauser/go-sysconf v0.3.13 // indirect
github.com/tklauser/numcpus v0.7.0 // indirect
github.com/tklauser/go-sysconf v0.3.16 // indirect
github.com/tklauser/numcpus v0.11.0 // indirect
github.com/twmb/murmur3 v1.1.7 // indirect
github.com/uber/jaeger-client-go v2.30.0+incompatible // indirect
github.com/uber/jaeger-lib v2.4.1+incompatible // indirect
Expand Down
24 changes: 12 additions & 12 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -1185,8 +1185,8 @@ github.com/eapache/go-xerial-snappy v0.0.0-20230731223053-c322873962e3 h1:Oy0F4A
github.com/eapache/go-xerial-snappy v0.0.0-20230731223053-c322873962e3/go.mod h1:YvSRo5mw33fLEx1+DlK6L2VV43tJt5Eyel9n9XBcR+0=
github.com/eapache/queue v1.1.0 h1:YOEu7KNc61ntiQlcEeUIoDTJ2o8mQznoNvUhiigpIqc=
github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I=
github.com/ebitengine/purego v0.8.4 h1:CF7LEKg5FFOsASUj0+QwaXf8Ht6TlFxg09+S9wz0omw=
github.com/ebitengine/purego v0.8.4/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
github.com/ebitengine/purego v0.9.1 h1:a/k2f2HQU3Pi399RPW1MOaZyhKJL9w/xFpKAg4q1s0A=
github.com/ebitengine/purego v0.9.1/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ=
github.com/echlebek/crock v1.0.1 h1:KbzamClMIfVIkkjq/GTXf+N16KylYBpiaTitO3f1ujg=
github.com/echlebek/crock v1.0.1/go.mod h1:/kvwHRX3ZXHj/kHWJkjXDmzzRow54EJuHtQ/PapL/HI=
github.com/echlebek/timeproxy v1.0.0 h1:V41/v8tmmMDNMA2GrBPI45nlXb3F7+OY+nJz1BqKsCk=
Expand Down Expand Up @@ -2310,8 +2310,8 @@ github.com/sensu/sensu-go/api/core/v2 v2.16.0/go.mod h1:MjM7+MCGEyTAgaZ589SiGHwY
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/shirou/gopsutil v3.21.11+incompatible h1:+1+c1VGhc88SSonWP6foOcLhvnKlUeu/erjjvaPEYiI=
github.com/shirou/gopsutil v3.21.11+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
github.com/shirou/gopsutil/v4 v4.25.5 h1:rtd9piuSMGeU8g1RMXjZs9y9luK5BwtnG7dZaQUJAsc=
github.com/shirou/gopsutil/v4 v4.25.5/go.mod h1:PfybzyydfZcN+JMMjkF6Zb8Mq1A/VcogFFg7hj50W9c=
github.com/shirou/gopsutil/v4 v4.25.12 h1:e7PvW/0RmJ8p8vPGJH4jvNkOyLmbkXgXW4m6ZPic6CY=
github.com/shirou/gopsutil/v4 v4.25.12/go.mod h1:EivAfP5x2EhLp2ovdpKSozecVXn1TmuG7SMzs/Wh4PU=
github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4=
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
Expand Down Expand Up @@ -2408,8 +2408,8 @@ github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/t3rm1n4l/go-mega v0.0.0-20241213150454-ec0027fb0002 h1:jevGbwKzMmHLgHAaDaMJLQX3jpXUWjUvnsrPeMgkM7o=
github.com/t3rm1n4l/go-mega v0.0.0-20241213150454-ec0027fb0002/go.mod h1:0Mv/XWQoRWF7d7jkc4DufsAJQg8xyZ5NtCkY59wECQY=
Expand Down Expand Up @@ -2453,10 +2453,10 @@ github.com/tj/go-buffer v1.1.0/go.mod h1:iyiJpfFcR2B9sXu7KvjbT9fpM4mOelRSDTbntVj
github.com/tj/go-elastic v0.0.0-20171221160941-36157cbbebc2/go.mod h1:WjeM0Oo1eNAjXGDx2yma7uG2XoyRZTq1uv3M/o7imD0=
github.com/tj/go-kinesis v0.0.0-20171128231115-08b17f58cb1b/go.mod h1:/yhzCV0xPfx6jb1bBgRFjl5lytqVqZXEaeqWP8lTEao=
github.com/tj/go-spin v1.1.0/go.mod h1:Mg1mzmePZm4dva8Qz60H2lHwmJ2loum4VIrLgVnKwh4=
github.com/tklauser/go-sysconf v0.3.13 h1:GBUpcahXSpR2xN01jhkNAbTLRk2Yzgggk8IM08lq3r4=
github.com/tklauser/go-sysconf v0.3.13/go.mod h1:zwleP4Q4OehZHGn4CYZDipCgg9usW5IJePewFCGVEa0=
github.com/tklauser/numcpus v0.7.0 h1:yjuerZP127QG9m5Zh/mSO4wqurYil27tHrqwRoRjpr4=
github.com/tklauser/numcpus v0.7.0/go.mod h1:bb6dMVcj8A42tSE7i32fsIUCbQNllK5iDguyOZRUzAY=
github.com/tklauser/go-sysconf v0.3.16 h1:frioLaCQSsF5Cy1jgRBrzr6t502KIIwQ0MArYICU0nA=
github.com/tklauser/go-sysconf v0.3.16/go.mod h1:/qNL9xxDhc7tx3HSRsLWNnuzbVfh3e7gh/BmM179nYI=
github.com/tklauser/numcpus v0.11.0 h1:nSTwhKH5e1dMNsCdVBukSZrURJRoHbSEQjdEbY+9RXw=
github.com/tklauser/numcpus v0.11.0/go.mod h1:z+LwcLq54uWZTX0u/bGobaV34u6V7KNlTZejzM6/3MQ=
github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
github.com/twmb/murmur3 v1.1.7 h1:ULWBiM04n/XoN3YMSJ6Z2pHDFLf+MeIVQU71ZPrvbWg=
Expand Down Expand Up @@ -3027,8 +3027,8 @@ golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw=
golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc=
golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
Expand Down
15 changes: 10 additions & 5 deletions plugins/inputs/mem/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,9 @@ This plugin collects metrics about the system memory.

## Global configuration options <!-- @/docs/includes/plugin_config.md -->

In addition to the plugin-specific configuration settings, plugins support
additional global and plugin configuration settings. These settings are used to
modify metrics, tags, and field or create aliases and configure ordering, etc.
See the [CONFIGURATION.md][CONFIGURATION.md] for more details.
Plugins support additional global and plugin configuration settings for tasks
such as modifying metrics, tags, and fields, creating aliases, and configuring
plugin ordering. See [CONFIGURATION.md][CONFIGURATION.md] for more details.

[CONFIGURATION.md]: ../../../docs/CONFIGURATION.md#plugins

Expand All @@ -36,6 +35,8 @@ Available fields are dependent on platform.
- mem
- fields:
- active (integer, Darwin, FreeBSD, Linux, OpenBSD)
- active_anon (integer, Linux)
- active_file (integer, Linux)
- available (integer)
- available_percent (float)
- buffered (integer, FreeBSD, Linux)
Expand All @@ -50,11 +51,14 @@ Available fields are dependent on platform.
- huge_page_size (integer, Linux)
- huge_pages_total (integer, Linux)
- inactive (integer, Darwin, FreeBSD, Linux, OpenBSD)
- inactive_anon (integer, Linux)
- inactive_file (integer, Linux)
- laundry (integer, FreeBSD)
- low_free (integer, Linux)
- low_total (integer, Linux)
- mapped (integer, Linux)
- page_tables (integer, Linux)
- percpu (integer, Linux)
- shared (integer, Linux)
- slab (integer, Linux)
- sreclaimable (integer, Linux)
Expand All @@ -63,6 +67,7 @@ Available fields are dependent on platform.
- swap_free (integer, Linux)
- swap_total (integer, Linux)
- total (integer)
- unevictable (integer, Linux)
- used (integer)
- used_percent (float)
- vmalloc_chunk (integer, Linux)
Expand All @@ -75,5 +80,5 @@ Available fields are dependent on platform.
## Example Output

```text
mem active=9299595264i,available=16818249728i,available_percent=80.41654254645131,buffered=2383761408i,cached=13316689920i,commit_limit=14751920128i,committed_as=11781156864i,dirty=122880i,free=1877688320i,high_free=0i,high_total=0i,huge_page_size=2097152i,huge_pages_free=0i,huge_pages_total=0i,inactive=7549939712i,low_free=0i,low_total=0i,mapped=416763904i,page_tables=19787776i,shared=670679040i,slab=2081071104i,sreclaimable=1923395584i,sunreclaim=157675520i,swap_cached=1302528i,swap_free=4286128128i,swap_total=4294963200i,total=20913917952i,used=3335778304i,used_percent=15.95004011996231,vmalloc_chunk=0i,vmalloc_total=35184372087808i,vmalloc_used=0i,wired=0i,write_back=0i,write_back_tmp=0i 1574712869000000000
mem active=9299595264i,active_anon=5765169152i,active_file=3534426112i,available=16818249728i,available_percent=80.41654254645131,buffered=2383761408i,cached=13316689920i,commit_limit=14751920128i,committed_as=11781156864i,dirty=122880i,free=1877688320i,high_free=0i,high_total=0i,huge_page_size=2097152i,huge_pages_free=0i,huge_pages_total=0i,inactive=7549939712i,inactive_anon=1081245696i,inactive_file=6468694016i,low_free=0i,low_total=0i,mapped=416763904i,page_tables=19787776i,percpu=5765120i,shared=670679040i,slab=2081071104i,sreclaimable=1923395584i,sunreclaim=157675520i,swap_cached=1302528i,swap_free=4286128128i,swap_total=4294963200i,total=20913917952i,unevictable=143360i,used=3335778304i,used_percent=15.95004011996231,vmalloc_chunk=0i,vmalloc_total=35184372087808i,vmalloc_used=0i,write_back=0i,write_back_tmp=0i 1574712869000000000
```
17 changes: 17 additions & 0 deletions plugins/inputs/mem/mem.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,15 @@ import (
//go:embed sample.conf
var sampleConfig string

// extendedMemoryStats provides extended memory statistics for a platform.
type extendedMemoryStats interface {
getFields() (map[string]interface{}, error)
}

type Mem struct {
ps psutil.PS
platform string
exStats extendedMemoryStats
}

func (*Mem) SampleConfig() string {
Expand All @@ -25,6 +31,9 @@ func (*Mem) SampleConfig() string {

func (ms *Mem) Init() error {
ms.platform = runtime.GOOS
if ms.exStats == nil {
ms.exStats = newExtendedMemoryStats()
}
return nil
}

Expand Down Expand Up @@ -92,6 +101,14 @@ func (ms *Mem) Gather(acc telegraf.Accumulator) error {
fields["vmalloc_used"] = vm.VmallocUsed
fields["write_back_tmp"] = vm.WriteBackTmp
fields["write_back"] = vm.WriteBack

extFields, err := ms.exStats.getFields()
if err != nil {
acc.AddError(fmt.Errorf("error getting extended virtual memory info: %w", err))
}
for k, v := range extFields {
fields[k] = v
}
}

acc.AddGauge("mem", fields, nil)
Expand Down
27 changes: 27 additions & 0 deletions plugins/inputs/mem/mem_linux.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package mem

import (
"github.com/shirou/gopsutil/v4/mem"
)

type linuxExtendedMemoryStats struct{}

func newExtendedMemoryStats() extendedMemoryStats {
return &linuxExtendedMemoryStats{}
}

// getFields returns extended virtual memory statistics from /proc/meminfo.
func (*linuxExtendedMemoryStats) getFields() (map[string]interface{}, error) {
exVM, err := mem.NewExLinux().VirtualMemory()
if err != nil {
return nil, err
}
return map[string]interface{}{
"active_file": exVM.ActiveFile,
"inactive_file": exVM.InactiveFile,
"active_anon": exVM.ActiveAnon,
"inactive_anon": exVM.InactiveAnon,
"unevictable": exVM.Unevictable,
"percpu": exVM.Percpu,
}, nil
}
149 changes: 149 additions & 0 deletions plugins/inputs/mem/mem_linux_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,149 @@
//go:build linux

package mem

import (
"testing"
"time"

"github.com/shirou/gopsutil/v4/mem"
"github.com/stretchr/testify/require"

"github.com/influxdata/telegraf"
"github.com/influxdata/telegraf/plugins/common/psutil"
"github.com/influxdata/telegraf/testutil"
)

// mockExtendedMemoryStats implements extendedMemoryStats for testing.
type mockExtendedMemoryStats struct {
fields map[string]interface{}
err error
}

func (m *mockExtendedMemoryStats) getFields() (map[string]interface{}, error) {
return m.fields, m.err
}

func TestMemStatsLinux(t *testing.T) {
var mps psutil.MockPS
defer mps.AssertExpectations(t)
var acc testutil.Accumulator

vms := &mem.VirtualMemoryStat{
Total: 16589934592,
Available: 8294967296,
Used: 8294967296,
Free: 2147483648,
Active: 4294967296,
Inactive: 2147483648,
Buffers: 536870912,
Cached: 2147483648,
Slab: 268435456,
Shared: 134217728,
Sreclaimable: 134217728,
Sunreclaim: 67108864,
CommitLimit: 8589934592,
CommittedAS: 4294967296,
Dirty: 1048576,
HighFree: 0,
HighTotal: 0,
HugePageSize: 2097152,
HugePagesFree: 0,
HugePagesTotal: 0,
LowFree: 2147483648,
LowTotal: 16589934592,
Mapped: 536870912,
PageTables: 33554432,
SwapCached: 0,
SwapFree: 8589934592,
SwapTotal: 8589934592,
VmallocChunk: 0,
VmallocTotal: 35184372088832,
VmallocUsed: 67108864,
WriteBack: 0,
WriteBackTmp: 0,
}

mps.On("VMStat").Return(vms, nil)

// Inject mock for extended memory stats
mockExStats := &mockExtendedMemoryStats{
fields: map[string]interface{}{
"active_file": uint64(1073741824),
"inactive_file": uint64(2147483648),
"active_anon": uint64(536870912),
"inactive_anon": uint64(268435456),
"unevictable": uint64(134217728),
"percpu": uint64(67108864),
},
}

plugin := &Mem{
ps: &mps,
exStats: mockExStats,
}

err := plugin.Init()
require.NoError(t, err)

plugin.platform = "linux"

err = plugin.Gather(&acc)
require.NoError(t, err)

expected := []telegraf.Metric{
testutil.MustMetric(
"mem",
map[string]string{},
map[string]interface{}{
// Common fields
"total": uint64(16589934592),
"available": uint64(8294967296),
"used": uint64(8294967296),
"used_percent": float64(8294967296) / float64(16589934592) * 100,
"available_percent": float64(8294967296) / float64(16589934592) * 100,
// Linux-specific fields from VirtualMemoryStat
"free": uint64(2147483648),
"buffered": uint64(536870912),
"cached": uint64(2147483648),
"active": uint64(4294967296),
"inactive": uint64(2147483648),
"slab": uint64(268435456),
"shared": uint64(134217728),
"sreclaimable": uint64(134217728),
"sunreclaim": uint64(67108864),
"commit_limit": uint64(8589934592),
"committed_as": uint64(4294967296),
"dirty": uint64(1048576),
"high_free": uint64(0),
"high_total": uint64(0),
"huge_page_size": uint64(2097152),
"huge_pages_free": uint64(0),
"huge_pages_total": uint64(0),
"low_free": uint64(2147483648),
"low_total": uint64(16589934592),
"mapped": uint64(536870912),
"page_tables": uint64(33554432),
"swap_cached": uint64(0),
"swap_free": uint64(8589934592),
"swap_total": uint64(8589934592),
"vmalloc_chunk": uint64(0),
"vmalloc_total": uint64(35184372088832),
"vmalloc_used": uint64(67108864),
"write_back": uint64(0),
"write_back_tmp": uint64(0),
// Extended fields from ExVirtualMemory (mocked)
"active_file": uint64(1073741824),
"inactive_file": uint64(2147483648),
"active_anon": uint64(536870912),
"inactive_anon": uint64(268435456),
"unevictable": uint64(134217728),
"percpu": uint64(67108864),
},
time.Unix(0, 0),
telegraf.Gauge,
),
}

testutil.RequireMetricsEqual(t, expected, acc.GetTelegrafMetrics(), testutil.IgnoreTime())
}
14 changes: 14 additions & 0 deletions plugins/inputs/mem/mem_other.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
//go:build !linux

package mem

type noopExtendedMemoryStats struct{}

func newExtendedMemoryStats() extendedMemoryStats {
return &noopExtendedMemoryStats{}
}

// getFields returns nil on non-Linux platforms as extended VM stats are not available.
func (*noopExtendedMemoryStats) getFields() (map[string]interface{}, error) {
return nil, nil
}
Loading
Loading