-
Notifications
You must be signed in to change notification settings - Fork 281
Expand file tree
/
Copy pathplugin.go
More file actions
116 lines (105 loc) · 3.52 KB
/
plugin.go
File metadata and controls
116 lines (105 loc) · 3.52 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
//go:build windows && lcow
package plugin
import (
"context"
"os"
"github.com/Microsoft/hcsshim/cmd/containerd-shim-lcow-v2/service"
"github.com/Microsoft/hcsshim/internal/logfields"
"github.com/Microsoft/hcsshim/internal/shim"
"github.com/Microsoft/hcsshim/internal/shimdiag"
hcsversion "github.com/Microsoft/hcsshim/internal/version"
"github.com/Microsoft/go-winio/pkg/etw"
"github.com/Microsoft/go-winio/pkg/etwlogrus"
"github.com/Microsoft/go-winio/pkg/guid"
"github.com/containerd/containerd/v2/pkg/shutdown"
"github.com/containerd/containerd/v2/plugins"
"github.com/containerd/plugin"
"github.com/containerd/plugin/registry"
"github.com/sirupsen/logrus"
)
const (
// etwProviderName is the ETW provider name for lcow shim.
etwProviderName = "Microsoft.Virtualization.containerd-shim-lcow-v2"
)
// svc holds the single Service instance created during plugin initialization.
var svc *service.Service
func init() {
// Provider ID: A6BD4B70-8A0B-5913-5C8E-E2780DC7F06F
// Provider and hook aren't closed explicitly, as they will exist until process exit.
provider, err := etw.NewProvider(etwProviderName, etwCallback)
if err != nil {
logrus.Error(err)
} else {
if hook, err := etwlogrus.NewHookFromProvider(provider); err == nil {
logrus.AddHook(hook)
} else {
logrus.Error(err)
}
}
// Write the "ShimLaunched" event with the shim's command-line arguments.
_ = provider.WriteEvent(
"ShimLaunched",
nil,
etw.WithFields(
etw.StringArray("Args", os.Args),
etw.StringField("Version", hcsversion.Version),
etw.StringField("GitCommit", hcsversion.Commit),
),
)
// Register the shim's TTRPC plugin with the containerd plugin registry.
// The plugin depends on the event publisher (for publishing task/sandbox
// events to containerd) and the internal shutdown service (for co-ordinated
// graceful teardown).
registry.Register(&plugin.Registration{
Type: plugins.TTRPCPlugin,
ID: "shim-services",
Requires: []plugin.Type{
plugins.EventPlugin,
plugins.InternalPlugin,
},
InitFn: func(ic *plugin.InitContext) (interface{}, error) {
pp, err := ic.GetByID(plugins.EventPlugin, "publisher")
if err != nil {
return nil, err
}
ss, err := ic.GetByID(plugins.InternalPlugin, "shutdown")
if err != nil {
return nil, err
}
// We will register all the services namely-
// 1. Sandbox service
// 2. Task service
// 3. Shimdiag service
svc = service.NewService(
ic.Context,
pp.(shim.Publisher),
ss.(shutdown.Service),
)
return svc, nil
},
})
}
// etwCallback is the ETW callback method for this shim.
//
// On a CaptureState notification (triggered by tools such as wpr or xperf) it
// dumps all goroutine stacks – both host-side Go stacks and, when available,
// the guest Linux stacks – to the logrus logger tagged with the sandbox ID.
// This provides an out-of-band diagnostic snapshot without requiring the shim
// to be paused or restarted.
func etwCallback(sourceID guid.GUID, state etw.ProviderState, level etw.Level, matchAnyKeyword uint64, matchAllKeyword uint64, filterData uintptr) {
if state == etw.ProviderStateCaptureState {
if svc == nil {
logrus.Warn("service not initialized")
return
}
resp, err := svc.DiagStacks(context.Background(), &shimdiag.StacksRequest{})
if err != nil {
return
}
log := logrus.WithField(logfields.SandboxID, svc.SandboxID())
log.WithField("stack", resp.Stacks).Info("goroutine stack dump")
if resp.GuestStacks != "" {
log.WithField("stack", resp.GuestStacks).Info("guest stack dump")
}
}
}