Skip to content

Commit b908218

Browse files
authored
feat: output the runtime log to the log file (#214)
Signed-off-by: chlins <[email protected]>
1 parent b1e3dbf commit b908218

File tree

17 files changed

+163
-8
lines changed

17 files changed

+163
-8
lines changed

cmd/root.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,10 @@ import (
2222
_ "net/http/pprof"
2323
"os"
2424
"os/signal"
25+
"path/filepath"
2526
"syscall"
2627

28+
"github.com/sirupsen/logrus"
2729
"github.com/spf13/cobra"
2830
"github.com/spf13/viper"
2931

@@ -33,6 +35,7 @@ import (
3335
)
3436

3537
var rootConfig *config.Root
38+
var logFile *os.File
3639

3740
// rootCmd represents the modctl command.
3841
var rootCmd = &cobra.Command{
@@ -53,10 +56,38 @@ var rootCmd = &cobra.Command{
5356
}()
5457
}
5558

59+
// Ensure log directory exists.
60+
if err := os.MkdirAll(rootConfig.LogDir, 0755); err != nil {
61+
return err
62+
}
63+
64+
// Ensure log file exists.
65+
var err error
66+
logFile, err = os.OpenFile(filepath.Join(rootConfig.LogDir, "modctl.log"), os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
67+
if err != nil {
68+
return err
69+
}
70+
71+
logLevel, err := logrus.ParseLevel(rootConfig.LogLevel)
72+
if err != nil {
73+
return err
74+
}
75+
76+
logrus.SetOutput(logFile)
77+
logrus.SetLevel(logLevel)
78+
logrus.SetFormatter(&logrus.TextFormatter{})
79+
5680
// TODO: need refactor as currently use a global flag to control the progress bar render.
5781
internalpb.SetDisableProgress(rootConfig.DisableProgress)
5882
return nil
5983
},
84+
PersistentPostRunE: func(cmd *cobra.Command, args []string) error {
85+
if logFile != nil {
86+
return logFile.Close()
87+
}
88+
89+
return nil
90+
},
6091
}
6192

6293
// Execute adds all child commands to the root command and sets flags appropriately.
@@ -88,6 +119,8 @@ func init() {
88119
flags.BoolVar(&rootConfig.Pprof, "pprof", rootConfig.Pprof, "enable pprof")
89120
flags.StringVar(&rootConfig.PprofAddr, "pprof-addr", rootConfig.PprofAddr, "specify the address for pprof")
90121
flags.BoolVar(&rootConfig.DisableProgress, "no-progress", rootConfig.DisableProgress, "disable progress bar")
122+
flags.StringVar(&rootConfig.LogDir, "log-dir", rootConfig.LogDir, "specify the log directory for modctl")
123+
flags.StringVar(&rootConfig.LogLevel, "log-level", rootConfig.LogLevel, "specify the log level for modctl")
91124

92125
// Bind common flags.
93126
if err := viper.BindPFlags(flags); err != nil {

pkg/backend/attach.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import (
2828
modelspec "github.com/CloudNativeAI/model-spec/specs-go/v1"
2929
godigest "github.com/opencontainers/go-digest"
3030
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
31+
"github.com/sirupsen/logrus"
3132

3233
internalpb "github.com/CloudNativeAI/modctl/internal/pb"
3334
"github.com/CloudNativeAI/modctl/pkg/backend/build"
@@ -59,6 +60,7 @@ var (
5960

6061
// Attach attaches user materials into the model artifact which follows the Model Spec.
6162
func (b *backend) Attach(ctx context.Context, filepath string, cfg *config.Attach) error {
63+
logrus.Infof("attaching file %s, cfg: %+v", filepath, cfg)
6264
srcManifest, err := b.getManifest(ctx, cfg.Source, cfg.OutputRemote, cfg.PlainHTTP, cfg.Insecure)
6365
if err != nil {
6466
return fmt.Errorf("failed to get source manifest: %w", err)
@@ -69,6 +71,8 @@ func (b *backend) Attach(ctx context.Context, filepath string, cfg *config.Attac
6971
return fmt.Errorf("failed to get source model config: %w", err)
7072
}
7173

74+
logrus.Infof("source model config: %+v", srcModelConfig)
75+
7276
var foundLayer *ocispec.Descriptor
7377
for _, layer := range srcManifest.Layers {
7478
if anno := layer.Annotations; anno != nil {
@@ -83,6 +87,8 @@ func (b *backend) Attach(ctx context.Context, filepath string, cfg *config.Attac
8387
}
8488
}
8589

90+
logrus.Infof("found original layer: %+v", foundLayer)
91+
8692
layers := srcManifest.Layers
8793
if foundLayer != nil {
8894
// Remove the found layer from the layers slice as we need to replace it with the new layer.
@@ -117,6 +123,8 @@ func (b *backend) Attach(ctx context.Context, filepath string, cfg *config.Attac
117123
layers = append(layers, newLayers...)
118124
sortLayers(layers)
119125

126+
logrus.Infof("new sorted layers: %+v", layers)
127+
120128
diffIDs := []godigest.Digest{}
121129
for _, layer := range layers {
122130
diffIDs = append(diffIDs, layer.Digest)
@@ -136,6 +144,9 @@ func (b *backend) Attach(ctx context.Context, filepath string, cfg *config.Attac
136144
Family: srcModelConfig.Descriptor.Family,
137145
Name: srcModelConfig.Descriptor.Name,
138146
}
147+
148+
logrus.Infof("new model config: %+v", modelConfig)
149+
139150
configDesc, err := builder.BuildConfig(ctx, layers, modelConfig, hooks.NewHooks(
140151
hooks.WithOnStart(func(name string, size int64, reader io.Reader) io.Reader {
141152
return pb.Add(internalpb.NormalizePrompt("Building config"), name, size, reader)

pkg/backend/build.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
modelspec "github.com/CloudNativeAI/model-spec/specs-go/v1"
2727
retry "github.com/avast/retry-go/v4"
2828
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
29+
"github.com/sirupsen/logrus"
2930

3031
internalpb "github.com/CloudNativeAI/modctl/internal/pb"
3132
"github.com/CloudNativeAI/modctl/pkg/backend/build"
@@ -45,6 +46,7 @@ const (
4546

4647
// Build builds the user materials into the model artifact which follows the Model Spec.
4748
func (b *backend) Build(ctx context.Context, modelfilePath, workDir, target string, cfg *config.Build) error {
49+
logrus.Infof("building model artifact: %s, cfg: %+v", target, cfg)
4850
// parse the repo name and tag name from target.
4951
ref, err := ParseReference(target)
5052
if err != nil {
@@ -97,6 +99,8 @@ func (b *backend) Build(ctx context.Context, modelfilePath, workDir, target stri
9799

98100
layers = append(layers, layerDescs...)
99101

102+
logrus.Infof("model artifact layers: %+v", layers)
103+
100104
revision := sourceInfo.Commit
101105
if revision != "" && sourceInfo.Dirty {
102106
revision += "-dirty"
@@ -114,6 +118,8 @@ func (b *backend) Build(ctx context.Context, modelfilePath, workDir, target stri
114118
SourceRevision: revision,
115119
}
116120

121+
logrus.Infof("model artifact config: %+v", modelConfig)
122+
117123
var configDesc ocispec.Descriptor
118124
// Build the model config.
119125
if err := retry.Do(func() error {

pkg/backend/build/builder.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import (
3434
godigest "github.com/opencontainers/go-digest"
3535
spec "github.com/opencontainers/image-spec/specs-go"
3636
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
37+
"github.com/sirupsen/logrus"
3738

3839
buildconfig "github.com/CloudNativeAI/modctl/pkg/backend/build/config"
3940
"github.com/CloudNativeAI/modctl/pkg/backend/build/hooks"
@@ -146,12 +147,15 @@ func (ab *abstractBuilder) BuildLayer(ctx context.Context, mediaType, workDir, p
146147
return ocispec.Descriptor{}, fmt.Errorf("failed to create codec: %w", err)
147148
}
148149

150+
logrus.Infof("building file %s...", relPath)
151+
149152
// Encode the content by codec depends on the media type.
150153
reader, err := codec.Encode(path, workDirPath)
151154
if err != nil {
152155
return ocispec.Descriptor{}, fmt.Errorf("failed to encode file: %w", err)
153156
}
154157

158+
logrus.Infof("calculating digest for %s...", relPath)
155159
// Calculate the digest of the encoded content.
156160
hash := sha256.New()
157161
size, err := io.Copy(hash, reader)
@@ -160,14 +164,17 @@ func (ab *abstractBuilder) BuildLayer(ctx context.Context, mediaType, workDir, p
160164
}
161165

162166
digest := fmt.Sprintf("sha256:%x", hash.Sum(nil))
167+
logrus.Infof("calculated digest for %s: %s", relPath, digest)
163168

164169
// Seek the reader to the beginning if supported,
165170
// otherwise we needs to re-encode the content again.
166171
if seeker, ok := reader.(io.ReadSeeker); ok {
172+
logrus.Infof("seeking %s reader to beginning...", relPath)
167173
if _, err := seeker.Seek(0, io.SeekStart); err != nil {
168174
return ocispec.Descriptor{}, fmt.Errorf("failed to seek reader: %w", err)
169175
}
170176
} else {
177+
logrus.Infof("%s reader is not seekable, re-encoding...", relPath)
171178
reader, err = codec.Encode(path, workDirPath)
172179
if err != nil {
173180
return ocispec.Descriptor{}, fmt.Errorf("failed to encode file: %w", err)
@@ -217,6 +224,8 @@ func (ab *abstractBuilder) BuildLayer(ctx context.Context, mediaType, workDir, p
217224
return desc, fmt.Errorf("failed to marshal metadata: %w", err)
218225
}
219226

227+
logrus.Infof("retrieved file %s metadata: %s", relPath, string(metadataStr))
228+
220229
// Apply the metadata to the descriptor annotation.
221230
if desc.Annotations == nil {
222231
desc.Annotations = make(map[string]string)

pkg/backend/extract.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
"github.com/CloudNativeAI/modctl/pkg/config"
2828
"github.com/CloudNativeAI/modctl/pkg/storage"
2929
modelspec "github.com/CloudNativeAI/model-spec/specs-go/v1"
30+
"github.com/sirupsen/logrus"
3031
"golang.org/x/sync/errgroup"
3132

3233
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
@@ -39,6 +40,7 @@ const (
3940

4041
// Extract extracts the model artifact.
4142
func (b *backend) Extract(ctx context.Context, target string, cfg *config.Extract) error {
43+
logrus.Infof("extracting model artifact: %s, cfg: %+v", target, cfg)
4244
// parse the repository and tag from the target.
4345
ref, err := ParseReference(target)
4446
if err != nil {
@@ -57,6 +59,8 @@ func (b *backend) Extract(ctx context.Context, target string, cfg *config.Extrac
5759
return fmt.Errorf("failed to unmarshal the manifest: %w", err)
5860
}
5961

62+
logrus.Infof("manifest: %s", string(manifestRaw))
63+
6064
return exportModelArtifact(ctx, b.store, manifest, repo, cfg)
6165
}
6266

@@ -65,13 +69,16 @@ func exportModelArtifact(ctx context.Context, store storage.Storage, manifest oc
6569
g, ctx := errgroup.WithContext(ctx)
6670
g.SetLimit(cfg.Concurrency)
6771

72+
logrus.Infof("extracting %d layers in total...", len(manifest.Layers))
6873
for _, layer := range manifest.Layers {
6974
g.Go(func() error {
7075
select {
7176
case <-ctx.Done():
7277
return ctx.Err()
7378
default:
7479
}
80+
81+
logrus.Infof("extracting layer %s...", layer.Digest.String())
7582
// pull the blob from the storage.
7683
reader, err := store.PullBlob(ctx, repo, layer.Digest.String())
7784
if err != nil {
@@ -84,6 +91,8 @@ func exportModelArtifact(ctx context.Context, store storage.Storage, manifest oc
8491
return fmt.Errorf("failed to extract layer %s: %w", layer.Digest.String(), err)
8592
}
8693

94+
logrus.Infof("extracted layer %s successfully", layer.Digest.String())
95+
8796
return nil
8897
})
8998
}

pkg/backend/fetch.go

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import (
2424

2525
modelspec "github.com/CloudNativeAI/model-spec/specs-go/v1"
2626
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
27+
"github.com/sirupsen/logrus"
2728
"golang.org/x/sync/errgroup"
2829

2930
internalpb "github.com/CloudNativeAI/modctl/internal/pb"
@@ -33,6 +34,7 @@ import (
3334

3435
// Fetch fetches partial files to the output.
3536
func (b *backend) Fetch(ctx context.Context, target string, cfg *config.Fetch) error {
37+
logrus.Infof("fetching partial files, target: %s, cfg: %+v", target, cfg)
3638
// parse the repository and tag from the target.
3739
ref, err := ParseReference(target)
3840
if err != nil {
@@ -57,6 +59,8 @@ func (b *backend) Fetch(ctx context.Context, target string, cfg *config.Fetch) e
5759
return fmt.Errorf("failed to decode the manifest: %w", err)
5860
}
5961

62+
logrus.Infof("manifest: %+v", manifest)
63+
6064
layers := []ocispec.Descriptor{}
6165
// filter the layers by patterns.
6266
for _, layer := range manifest.Layers {
@@ -85,6 +89,7 @@ func (b *backend) Fetch(ctx context.Context, target string, cfg *config.Fetch) e
8589
g, ctx := errgroup.WithContext(ctx)
8690
g.SetLimit(cfg.Concurrency)
8791

92+
logrus.Infof("fetching %d layers in total...", len(layers))
8893
for _, layer := range layers {
8994
g.Go(func() error {
9095
select {
@@ -93,9 +98,16 @@ func (b *backend) Fetch(ctx context.Context, target string, cfg *config.Fetch) e
9398
default:
9499
}
95100

96-
return pullAndExtractFromRemote(ctx, pb, internalpb.NormalizePrompt("Fetching blob"), client, cfg.Output, layer)
101+
logrus.Infof("fetching layer %s...", layer.Digest)
102+
if err := pullAndExtractFromRemote(ctx, pb, internalpb.NormalizePrompt("Fetching blob"), client, cfg.Output, layer); err != nil {
103+
return err
104+
}
105+
106+
logrus.Infof("layer %s fetched successfully", layer.Digest)
107+
return nil
97108
})
98109
}
99110

111+
logrus.Infof("fetched %d layers in total successfully", len(layers))
100112
return g.Wait()
101113
}

pkg/backend/inspect.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"time"
2424

2525
godigest "github.com/opencontainers/go-digest"
26+
"github.com/sirupsen/logrus"
2627

2728
"github.com/CloudNativeAI/modctl/pkg/config"
2829
modelspec "github.com/CloudNativeAI/model-spec/specs-go/v1"
@@ -66,6 +67,7 @@ type InspectedModelArtifactLayer struct {
6667

6768
// Inspect inspects the target from the storage.
6869
func (b *backend) Inspect(ctx context.Context, target string, cfg *config.Inspect) (*InspectedModelArtifact, error) {
70+
logrus.Infof("inspecting target: %s, cfg: %+v", target, cfg)
6971
_, err := ParseReference(target)
7072
if err != nil {
7173
return nil, fmt.Errorf("failed to parse target: %w", err)
@@ -81,11 +83,15 @@ func (b *backend) Inspect(ctx context.Context, target string, cfg *config.Inspec
8183
return nil, fmt.Errorf("failed to marshal manifest: %w", err)
8284
}
8385

86+
logrus.Infof("manifest: %s", string(manifestRaw))
87+
8488
config, err := b.getModelConfig(ctx, target, manifest.Config, cfg.Remote, cfg.PlainHTTP, cfg.Insecure)
8589
if err != nil {
8690
return nil, fmt.Errorf("failed to get config: %w", err)
8791
}
8892

93+
logrus.Infof("model config: %+v", config)
94+
8995
inspectedModelArtifact := &InspectedModelArtifact{
9096
ID: manifest.Config.Digest.String(),
9197
Digest: godigest.FromBytes(manifestRaw).String(),

pkg/backend/list.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ import (
2424
"time"
2525

2626
modelspec "github.com/CloudNativeAI/model-spec/specs-go/v1"
27-
2827
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
28+
"github.com/sirupsen/logrus"
2929
)
3030

3131
// ModelArtifact is the data model to represent the model artifact.
@@ -44,6 +44,7 @@ type ModelArtifact struct {
4444

4545
// List lists all the model artifacts.
4646
func (b *backend) List(ctx context.Context) ([]*ModelArtifact, error) {
47+
logrus.Info("listing model artifacts")
4748
modelArtifacts := []*ModelArtifact{}
4849

4950
// list all the repositories.
@@ -52,13 +53,17 @@ func (b *backend) List(ctx context.Context) ([]*ModelArtifact, error) {
5253
return nil, fmt.Errorf("failed to list repositories: %w", err)
5354
}
5455

56+
logrus.Infof("listed %d repositories: %+v", len(repos), repos)
57+
5558
// list all the tags in the repository.
5659
for _, repo := range repos {
5760
tags, err := b.store.ListTags(ctx, repo)
5861
if err != nil {
5962
return nil, fmt.Errorf("failed to list tags in repository %s: %w", repo, err)
6063
}
6164

65+
logrus.Infof("listed %d tags in repository %s: %+v", len(tags), repo, tags)
66+
6267
// assemble the model artifact.
6368
for _, tag := range tags {
6469
modelArtifact, err := b.assembleModelArtifact(ctx, repo, tag)

0 commit comments

Comments
 (0)