# tapEffect

Runs an effectful observation before forwarding each successful input unchanged.

## Signatures

```ts
export declare const tapEffect: {
    <A, E2, R2>(f: (a: A) => Effect.Effect<unknown, E2, R2>): <E, R>(sink: Sink<A, E | E2, R>) => Sink<A, E | E2, R | R2>;
    <A, E, R, E2, R2>(sink: Sink<A, E | E2, R>, f: (a: A) => Effect.Effect<unknown, E2, R2>): Sink<A, E | E2, R | R2>;
};
```

## Why

Logging, metrics, and other observations can be attached at the consumer boundary without
changing the value type.

## Ownership and lifetime

The tap Effect completes before the value is forwarded. If it fails, its Cause is delivered and
the value is not forwarded. The producer controls call order and concurrency; tap services and
interruption are reflected by the returned sink.

## Examples

```ts
import { Effect } from "effect"
import * as Sink from "@typed/fx/Sink"
const observed = Sink.tapEffect(Sink.make(Effect.logError, Effect.log), (n: number) => Effect.log(`saw ${n}`))
```
