Source file src/cmd/vendor/golang.org/x/telemetry/internal/upload/date.go

     1  // Copyright 2023 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  package upload
     6  
     7  import (
     8  	"fmt"
     9  	"os"
    10  	"sync"
    11  	"time"
    12  
    13  	"golang.org/x/telemetry/internal/counter"
    14  )
    15  
    16  // time and date handling
    17  
    18  var distantPast = 21 * 24 * time.Hour
    19  
    20  // reports that are too old (21 days) are not uploaded
    21  func (u *uploader) tooOld(date string, uploadStartTime time.Time) bool {
    22  	t, err := time.Parse(time.DateOnly, date)
    23  	if err != nil {
    24  		u.logger.Printf("tooOld: %v", err)
    25  		return false
    26  	}
    27  	age := uploadStartTime.Sub(t)
    28  	return age > distantPast
    29  }
    30  
    31  // counterDateSpan parses the counter file named fname and returns the (begin,
    32  // end) span recorded in its metadata, or an error if this data could not be
    33  // extracted.
    34  func (u *uploader) counterDateSpan(fname string) (begin, end time.Time, _ error) {
    35  	parsed, err := u.parseCountFile(fname)
    36  	if err != nil {
    37  		return time.Time{}, time.Time{}, err
    38  	}
    39  	timeBegin, ok := parsed.Meta["TimeBegin"]
    40  	if !ok {
    41  		return time.Time{}, time.Time{}, fmt.Errorf("missing counter metadata for TimeBegin")
    42  	}
    43  	begin, err = time.Parse(time.RFC3339, timeBegin)
    44  	if err != nil {
    45  		return time.Time{}, time.Time{}, fmt.Errorf("failed to parse TimeBegin: %v", err)
    46  	}
    47  	timeEnd, ok := parsed.Meta["TimeEnd"]
    48  	if !ok {
    49  		return time.Time{}, time.Time{}, fmt.Errorf("missing counter metadata for TimeEnd")
    50  	}
    51  	end, err = time.Parse(time.RFC3339, timeEnd)
    52  	if err != nil {
    53  		return time.Time{}, time.Time{}, fmt.Errorf("failed to parse TimeEnd: %v", err)
    54  	}
    55  	return begin, end, nil
    56  }
    57  
    58  // avoid parsing count files multiple times
    59  type parsedCache struct {
    60  	mu sync.Mutex
    61  	m  map[string]*counter.File
    62  }
    63  
    64  func (u *uploader) parseCountFile(fname string) (*counter.File, error) {
    65  	u.cache.mu.Lock()
    66  	defer u.cache.mu.Unlock()
    67  	if u.cache.m == nil {
    68  		u.cache.m = make(map[string]*counter.File)
    69  	}
    70  	if f, ok := u.cache.m[fname]; ok {
    71  		return f, nil
    72  	}
    73  	buf, err := os.ReadFile(fname)
    74  	if err != nil {
    75  		return nil, fmt.Errorf("parse ReadFile: %v for %s", err, fname)
    76  	}
    77  	f, err := counter.Parse(fname, buf)
    78  	if err != nil {
    79  
    80  		return nil, fmt.Errorf("parse Parse: %v for %s", err, fname)
    81  	}
    82  	u.cache.m[fname] = f
    83  	return f, nil
    84  }
    85  

View as plain text