...

Source file src/cuelabs.dev/go/oci/ociregistry/ocidebug/debug.go

Documentation: cuelabs.dev/go/oci/ociregistry/ocidebug

     1  // Copyright 2023 CUE Labs AG
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  // Package ocidebug is an OCI registry wrapper that prints log messages
    16  // on registry operations.
    17  package ocidebug
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  	"io"
    23  	"log"
    24  	"sync/atomic"
    25  
    26  	"cuelabs.dev/go/oci/ociregistry"
    27  )
    28  
    29  func New(r ociregistry.Interface, logf func(f string, a ...any)) ociregistry.Interface {
    30  	if logf == nil {
    31  		logf = log.Printf
    32  	}
    33  	return &logger{
    34  		logf: logf,
    35  		r:    r,
    36  	}
    37  }
    38  
    39  var blobWriterID int32
    40  
    41  type logger struct {
    42  	logf func(f string, a ...any)
    43  	r    ociregistry.Interface
    44  	*ociregistry.Funcs
    45  }
    46  
    47  func (r *logger) DeleteBlob(ctx context.Context, repoName string, digest ociregistry.Digest) error {
    48  	r.logf("DeleteBlob %s %s {", repoName, digest)
    49  	err := r.r.DeleteBlob(ctx, repoName, digest)
    50  	r.logf("} -> %v", err)
    51  	return err
    52  }
    53  
    54  func (r *logger) DeleteManifest(ctx context.Context, repoName string, digest ociregistry.Digest) error {
    55  	r.logf("DeleteManifest %s %s {", repoName, digest)
    56  	err := r.r.DeleteManifest(ctx, repoName, digest)
    57  	r.logf("} -> %v", err)
    58  	return err
    59  }
    60  
    61  func (r *logger) DeleteTag(ctx context.Context, repoName string, tagName string) error {
    62  	r.logf("DeleteTag %s %s {", repoName, tagName)
    63  	err := r.r.DeleteTag(ctx, repoName, tagName)
    64  	r.logf("} -> %v", err)
    65  	return err
    66  }
    67  
    68  func (r *logger) GetBlob(ctx context.Context, repoName string, dig ociregistry.Digest) (ociregistry.BlobReader, error) {
    69  	r.logf("GetBlob %s %s {", repoName, dig)
    70  	rd, err := r.r.GetBlob(ctx, repoName, dig)
    71  	r.logf("} -> %T, %v", rd, err)
    72  	return rd, err
    73  }
    74  
    75  func (r *logger) GetBlobRange(ctx context.Context, repoName string, dig ociregistry.Digest, o0, o1 int64) (ociregistry.BlobReader, error) {
    76  	r.logf("GetBlob %s %s [%d, %d] {", repoName, dig, o0, o1)
    77  	rd, err := r.r.GetBlobRange(ctx, repoName, dig, o0, o1)
    78  	r.logf("} -> %T, %v", rd, err)
    79  	return rd, err
    80  }
    81  
    82  func (r *logger) GetManifest(ctx context.Context, repoName string, dig ociregistry.Digest) (ociregistry.BlobReader, error) {
    83  	r.logf("GetManifest %s %s {", repoName, dig)
    84  	rd, err := r.r.GetManifest(ctx, repoName, dig)
    85  	r.logf("} -> %T, %v", rd, err)
    86  	return rd, err
    87  }
    88  
    89  func (r *logger) GetTag(ctx context.Context, repoName string, tagName string) (ociregistry.BlobReader, error) {
    90  	r.logf("GetTag %s %s {", repoName, tagName)
    91  	rd, err := r.r.GetTag(ctx, repoName, tagName)
    92  	r.logf("} -> %T, %v", rd, err)
    93  	return rd, err
    94  }
    95  
    96  func (r *logger) MountBlob(ctx context.Context, fromRepo, toRepo string, dig ociregistry.Digest) (ociregistry.Descriptor, error) {
    97  	r.logf("MountBlob from=%s to=%s digest=%s {", fromRepo, toRepo, dig)
    98  	desc, err := r.r.MountBlob(ctx, fromRepo, toRepo, dig)
    99  	r.logf("} -> %#v, %v", desc, err)
   100  	return desc, err
   101  }
   102  
   103  func (r *logger) PushBlob(ctx context.Context, repoName string, desc ociregistry.Descriptor, content io.Reader) (ociregistry.Descriptor, error) {
   104  	r.logf("PushBlob %s %#v %T {", repoName, desc, content)
   105  	desc, err := r.r.PushBlob(ctx, repoName, desc, content)
   106  	if err != nil {
   107  		r.logf("} -> %v", err)
   108  	} else {
   109  		r.logf("} -> %#v", desc)
   110  	}
   111  	return desc, err
   112  }
   113  
   114  func (r *logger) PushBlobChunked(ctx context.Context, repoName string, chunkSize int) (ociregistry.BlobWriter, error) {
   115  	bwid := fmt.Sprintf("bw%d", atomic.AddInt32(&blobWriterID, 1))
   116  	r.logf("PushBlobChunked %s chunkSize=%d {", repoName, chunkSize)
   117  	w, err := r.r.PushBlobChunked(ctx, repoName, chunkSize)
   118  	r.logf("} -> %T(%s), %v", w, bwid, err)
   119  	return blobWriter{
   120  		id: bwid,
   121  		w:  w,
   122  		r:  r,
   123  	}, err
   124  }
   125  
   126  func (r *logger) PushBlobChunkedResume(ctx context.Context, repoName, id string, offset int64, chunkSize int) (ociregistry.BlobWriter, error) {
   127  	bwid := fmt.Sprintf("bw%d", atomic.AddInt32(&blobWriterID, 1))
   128  	r.logf("PushBlobChunkedResume %s id=%q offset=%d chunkSize=%d {", repoName, id, offset, chunkSize)
   129  	w, err := r.r.PushBlobChunkedResume(ctx, repoName, id, offset, chunkSize)
   130  	r.logf("} -> %T(%s), %v", w, bwid, err)
   131  	return blobWriter{
   132  		id: bwid,
   133  		w:  w,
   134  		r:  r,
   135  	}, err
   136  }
   137  
   138  func (r *logger) PushManifest(ctx context.Context, repoName string, tag string, data []byte, mediaType string) (ociregistry.Descriptor, error) {
   139  	r.logf("PushManifest %s tag=%q mediaType=%q data=%q {", repoName, tag, mediaType, data)
   140  	desc, err := r.r.PushManifest(ctx, repoName, tag, data, mediaType)
   141  	if err != nil {
   142  		r.logf("} -> %v", err)
   143  	} else {
   144  		r.logf("} -> %#v", desc)
   145  	}
   146  	return desc, err
   147  }
   148  
   149  func (r *logger) Referrers(ctx context.Context, repoName string, digest ociregistry.Digest, artifactType string) ociregistry.Seq[ociregistry.Descriptor] {
   150  	return logIterReturn(
   151  		r,
   152  		fmt.Sprintf("Referrers %s %s %q", repoName, digest, artifactType),
   153  		r.r.Referrers(ctx, repoName, digest, artifactType),
   154  	)
   155  }
   156  
   157  func (r *logger) Repositories(ctx context.Context, startAfter string) ociregistry.Seq[string] {
   158  	return logIterReturn(
   159  		r,
   160  		fmt.Sprintf("Repositories startAfter: %q", startAfter),
   161  		r.r.Repositories(ctx, startAfter),
   162  	)
   163  }
   164  
   165  func (r *logger) Tags(ctx context.Context, repoName string, startAfter string) ociregistry.Seq[string] {
   166  	return logIterReturn(
   167  		r,
   168  		fmt.Sprintf("Tags %s startAfter: %q", repoName, startAfter),
   169  		r.r.Tags(ctx, repoName, startAfter),
   170  	)
   171  }
   172  
   173  func (r *logger) ResolveBlob(ctx context.Context, repoName string, digest ociregistry.Digest) (ociregistry.Descriptor, error) {
   174  	r.logf("ResolveBlob %s %s {", repoName, digest)
   175  	desc, err := r.r.ResolveBlob(ctx, repoName, digest)
   176  	if err != nil {
   177  		r.logf("} -> %v", err)
   178  	} else {
   179  		r.logf("} -> %#v", desc)
   180  	}
   181  	return desc, err
   182  }
   183  
   184  func (r *logger) ResolveManifest(ctx context.Context, repoName string, digest ociregistry.Digest) (ociregistry.Descriptor, error) {
   185  	r.logf("ResolveManifest %s %s {", repoName, digest)
   186  	desc, err := r.r.ResolveManifest(ctx, repoName, digest)
   187  	if err != nil {
   188  		r.logf("} -> %v", err)
   189  	} else {
   190  		r.logf("} -> %#v", desc)
   191  	}
   192  	return desc, err
   193  }
   194  
   195  func (r *logger) ResolveTag(ctx context.Context, repoName string, tagName string) (ociregistry.Descriptor, error) {
   196  	r.logf("ResolveTag %s %s {", repoName, tagName)
   197  	desc, err := r.r.ResolveTag(ctx, repoName, tagName)
   198  	if err != nil {
   199  		r.logf("} -> %v", err)
   200  	} else {
   201  		r.logf("} -> %#v", desc)
   202  	}
   203  	return desc, err
   204  }
   205  
   206  type blobWriter struct {
   207  	id string
   208  	r  *logger
   209  	w  ociregistry.BlobWriter
   210  }
   211  
   212  func (w blobWriter) logf(f string, a ...any) {
   213  	w.r.logf("%s: %s", w.id, fmt.Sprintf(f, a...))
   214  }
   215  
   216  func (w blobWriter) Write(buf []byte) (int, error) {
   217  	w.logf("Write %q {", buf)
   218  	n, err := w.w.Write(buf)
   219  	w.logf("} -> %v, %v", n, err)
   220  	return n, err
   221  }
   222  
   223  func (w blobWriter) ID() string {
   224  	return w.w.ID()
   225  }
   226  
   227  func (w blobWriter) Size() int64 {
   228  	size := w.w.Size()
   229  	w.logf("Size -> %v", size)
   230  	return size
   231  }
   232  
   233  func (w blobWriter) ChunkSize() int {
   234  	chunkSize := w.w.ChunkSize()
   235  	w.logf("ChunkSize -> %v", chunkSize)
   236  	return chunkSize
   237  }
   238  
   239  func (w blobWriter) Close() error {
   240  	w.logf("Close {")
   241  	err := w.w.Close()
   242  	w.logf("} -> %v", err)
   243  	return err
   244  }
   245  
   246  func (w blobWriter) Commit(digest ociregistry.Digest) (ociregistry.Descriptor, error) {
   247  	w.logf("Commit %q {", digest)
   248  	desc, err := w.w.Commit(digest)
   249  	w.logf("} -> %#v, %v", desc, err)
   250  	return desc, err
   251  }
   252  
   253  func (w blobWriter) Cancel() error {
   254  	w.logf("Cancel {")
   255  	err := w.w.Cancel()
   256  	w.logf("} -> %v", err)
   257  	return err
   258  }
   259  
   260  func logIterReturn[T any](r *logger, initialMsg string, it ociregistry.Seq[T]) ociregistry.Seq[T] {
   261  	return func(yield func(T, error) bool) {
   262  		r.logf("%s {", initialMsg)
   263  		items := []T{}
   264  		var _err error
   265  		it(func(item T, err error) bool {
   266  			if err != nil {
   267  				yield(*new(T), err)
   268  				_err = err
   269  				return false
   270  			}
   271  			ok := yield(item, err)
   272  			if ok {
   273  				items = append(items, item)
   274  			}
   275  			return ok
   276  		})
   277  		if _err != nil {
   278  			if len(items) > 0 {
   279  				r.logf("} -> %#v, %v", items, _err)
   280  			} else {
   281  				r.logf("} -> %v", _err)
   282  			}
   283  		} else {
   284  			r.logf("} -> %#v", items)
   285  		}
   286  	}
   287  }
   288  

View as plain text