## Keeping information passed by the receiver's factory

Now that you have implemented the `receiver.Traces` interface methods, your
`tailtracer` receiver component is ready to be instantiated and returned by its
factory.

Open the `tailtracer/factory.go` file and navigate to the
`createTracesReceiver()` function. Notice that the factory will pass references
as part of the `createTracesReceiver()` function parameters that your receiver
requires to work properly. These include its configuration settings
(`component.Config`), the next `Consumer` in the pipeline that will consume the
generated traces (`consumer.Traces`), and the Collector logger. This is so that
the `tailtracer` receiver can add meaningful events to it (`receiver.Settings`).

Given that all this information will only be made available to the receiver at
the moment it is instantiated by the factory, the `tailtracerReceiver` type will
need fields to keep that information and use it in other stages of its
lifecycle.

Here is what the `trace-receiver.go` file looks like with the updated
`tailtracerReceiver` type declaration:

> tailtracer/trace-receiver.go

```go
package tailtracer

import (
	"context"
	"time"
	"go.opentelemetry.io/collector/component"
	"go.opentelemetry.io/collector/consumer"
	"go.uber.org/zap"
)

type tailtracerReceiver struct {
	host         component.Host
	cancel       context.CancelFunc
	logger       *zap.Logger
	nextConsumer consumer.Traces
	config       *Config
}

func (tailtracerRcvr *tailtracerReceiver) Start(ctx context.Context, host component.Host) error {
	tailtracerRcvr.host = host
	ctx = context.Background()
	ctx, tailtracerRcvr.cancel = context.WithCancel(ctx)

	interval, _ := time.ParseDuration(tailtracerRcvr.config.Interval)
	go func() {
		ticker := time.NewTicker(interval)
		defer ticker.Stop()

		for {
			select {
				case <-ticker.C:
					tailtracerRcvr.logger.Info("I should start processing traces now!")
				case <-ctx.Done():
					return
			}
		}
	}()

	return nil
}

func (tailtracerRcvr *tailtracerReceiver) Shutdown(ctx context.Context) error {
	if tailtracerRcvr.cancel != nil {
		tailtracerRcvr.cancel()
	}
	return nil
}
```

> [!NOTE] Check your work
>
> - Imported the `go.opentelemetry.io/collector/consumer` which is where the
>   pipeline's consumer types and interfaces are declared.
> - Imported the `go.uber.org/zap` package, which is what the Collector uses for
>   its debugging capabilities.
> - Added a `zap.Logger` field named `logger` so we can have access to the
>   Collector logger reference from within the receiver.
> - Added a `consumer.Traces` field named `nextConsumer` so we can push the
>   traces generated by the `tailtracer` receiver to the next consumer, declared
>   in the Collector pipeline.
> - Added a `Config` field named `config` so we can have access to receiver's
>   configuration settings defined in the Collector config.
> - Added a variable named `interval` that is initialized as a `time.Duration`
>   based on the value of the `interval` settings of the `tailtracer` receiver,
>   defined in the Collector config.
> - Added a `go func()` to implement the `ticker` mechanism so the receiver can
>   generate traces every time the `ticker` reaches the amount of time specified
>   by the `interval` variable.
> - Used the `tailtracerRcvr.logger` field to generate an info message every
>   time the receiver is supposed to generate traces.

The `tailtracerReceiver` type is ready to be instantiated and will keep all
meaningful information passed by its factory.

Open the `tailtracer/factory.go` file and navigate to the
`createTracesReceiver()` function.

The receiver is only instantiated if it is declared as a component in a
pipeline, and the factory is responsible to make sure the next consumer (either
a processor or exporter) in the pipeline is valid. Otherwise, it should generate
an error.

The `createTracesReceiver()` function will need a guard clause to make that
validation.

You will also need variables to properly initialize the `config` and the
`logger` fields of the `tailtracerReceiver` instance.

Here is what the `factory.go` file looks like with the updated
`createTracesReceiver()` function:

> tailtracer/factory.go

```go
package tailtracer

import (
	"context"
	"time"

	"go.opentelemetry.io/collector/component"
	"go.opentelemetry.io/collector/consumer"
	"go.opentelemetry.io/collector/receiver"
)

var (
	typeStr         = component.MustNewType("tailtracer")
)

const (
	defaultInterval = 1 * time.Minute
)

func createDefaultConfig() component.Config {
	return &Config{
		Interval: string(defaultInterval),
	}
}

func createTracesReceiver(_ context.Context, params receiver.Settings, baseCfg component.Config, consumer consumer.Traces) (receiver.Traces, error) {

	logger := params.Logger
	tailtracerCfg := baseCfg.(*Config)

	traceRcvr := &tailtracerReceiver{
		logger:       logger,
		nextConsumer: consumer,
		config:       tailtracerCfg,
	}

	return traceRcvr, nil
}

// NewFactory creates a factory for tailtracer receiver.
func NewFactory() receiver.Factory {
	return receiver.NewFactory(
		typeStr,
		createDefaultConfig,
		receiver.WithTraces(createTracesReceiver, component.StabilityLevelAlpha))
}
```

> [!NOTE] Check your work
>
> - Added a variable called `logger` and initialized it with the Collector
>   logger that is available as a field named `Logger`, in the
>   `receiver.Settings` reference.
> - Added a variable called `tailtracerCfg` and initialized it by casting the
>   `component.Config` reference to the `tailtracer` receiver `Config`.
> - Added a variable called `traceRcvr` and initialized it with the
>   `tailtracerReceiver` instance using the factory information stored in the
>   variables.
> - Updated the return statement to include the `traceRcvr` instance.

So far, the skeleton of the receiver has been fully implemented.