func NewPcapWriter()

in pcap-cli/pkg/pcap/pcap_writer.go [162:218]


func NewPcapWriter(ctx context.Context, ifaceAndInfex, template, extension, timezone *string, interval int) (PcapWriter, error) {
	isStdOutOrErr := isStdoutPcapWriter(template, extension, &interval)

	loggerPrefix := fmt.Sprintf("[pcap/writer] - [%s] – ", *ifaceAndInfex)
	if isStdOutOrErr {
		loggerPrefix += "[stdout] – "
	} else {
		loggerPrefix = fmt.Sprintf("%s[%s] - ", loggerPrefix, *extension)
	}
	logger := log.New(os.Stderr, loggerPrefix, log.LstdFlags)

	var err error
	var writer *logrotate.Writer

	if isStdOutOrErr {
		// Using `logrotate` to make `os.Stdout` safe to be concurrently written by PCAP engines
		writer, err = newPcapWriterForStdout(logger)
	} else {
		writer, err = newPcapWriter(logger, template, extension, timezone, &interval)
	}

	if err != nil {
		return nil, err
	}

	// `logrotate` does not provide handles to `*bufio.Writer::Flush`/`*os.File::Syinc`
	// the underlying Writer/File so it is necessary to get handles on them.
	// Since PCAP engines are started atomically and current execution must complete
	// before a new one can be started; it is safe to `flush` and `sync` PCAP files.
	// https://github.com/easyCZ/logrotate/blob/master/writer.go
	v := reflect.ValueOf(writer)
	osFile := getSetableField(v, "f")
	osFileSync := osFile.MethodByName("Sync")
	bufioWriter := getSetableField(v, "bw")
	bufioWriterFlush := bufioWriter.MethodByName("Flush")

	if isStdOutOrErr {
		// injecting `os.Stdout` into `logrotate.Writer` instance
		osFile.Set(reflect.ValueOf(os.Stdout))
		bufioWriter.Set(reflect.ValueOf(bufio.NewWriterSize(os.Stdout, 1)))
	}

	w := &pcapWriter{writer, ifaceAndInfex, isStdOutOrErr, v, osFile, osFileSync, bufioWriter, bufioWriterFlush}

	go func(ctx context.Context, writer *logrotate.Writer, block bool) {
		if !block {
			return
		}
		<-ctx.Done()
		logger.Println("- ROTATE")
		rotate(writer)
	}(ctx, writer, !isStdOutOrErr)

	logger.Println("- created")

	return w, nil
}