By default, ExoPlayer only logs errors. To log player events, the `EventLogger`
class can be used. The additional logging it provides can be helpful for
understanding what the player is doing, as well as for debugging playback
issues. `EventLogger` implements `AnalyticsListener`, so you can register an
instance with an `ExoPlayer`:


### Kotlin

```kotlin
player.addAnalyticsListener(EventLogger())
```

### Java

```java
player.addAnalyticsListener(new EventLogger());
```

<br />

To observe the log, use Android Studio's [logcat tab](https://developer.android.com/studio/debug/am-logcat). You can select your
app as debuggable process by the package name (`androidx.media3.demo.main` if
using the demo app) and tell the logcat tab to log only for that app by
selecting **show only selected application** . It's possible to further filter
the logging with the expression `EventLogger|ExoPlayerImpl`, to get only logging
from `EventLogger` and the player itself.

An alternative to using Android Studio's logcat tab is to use the console. For
example:

```bash
adb logcat EventLogger:* ExoPlayerImpl:* *:s
```

### Player information

The `ExoPlayerImpl` class delivers two important lines about the player version,
the device and OS the app is running on, active [feature flags](https://developer.android.com/media/media3/exoplayer/flags.md.txt), and the
modules of ExoPlayer that have been loaded:

    ExoPlayerImpl: Init 59a18ab [AndroidXMedia3/1.0.0-rc02] [flame, Pixel 4, Google, 33] [Canary:ON]
    ExoPlayerImpl: Release 59a18ab [AndroidXMedia3/1.0.0-rc02] [flame, Pixel 4, Google, 33] [media3.common, media3.datasource, media3.ui, media3.exoplayer, media3.decoder, media3.exoplayer.dash, media3.extractor]

### Playback state

Player state changes are logged in lines like these:

    EventLogger: playWhenReady [eventTime=0.00, mediaPos=0.00, window=0, true, USER_REQUEST]
    EventLogger: state [eventTime=0.01, mediaPos=0.00, window=0, BUFFERING]
    EventLogger: state [eventTime=0.93, mediaPos=0.00, window=0, period=0, READY]
    EventLogger: isPlaying [eventTime=0.93, mediaPos=0.00, window=0, period=0, true]
    EventLogger: playWhenReady [eventTime=9.40, mediaPos=8.40, window=0, period=0, false, USER_REQUEST]
    EventLogger: isPlaying [eventTime=9.40, mediaPos=8.40, window=0, period=0, false]
    EventLogger: playWhenReady [eventTime=10.40, mediaPos=8.40, window=0, period=0, true, USER_REQUEST]
    EventLogger: isPlaying [eventTime=10.40, mediaPos=8.40, window=0, period=0, true]
    EventLogger: state [eventTime=20.40, mediaPos=18.40, window=0, period=0, ENDED]
    EventLogger: isPlaying [eventTime=20.40, mediaPos=18.40, window=0, period=0, false]

In this example playback starts 0.93 seconds after the player is prepared. The
user pauses playback after 9.4 seconds, and resumes playback one second later at
10.4 seconds. Playback ends ten seconds later at 20.4 seconds. The common
elements within the square brackets are:

- `[eventTime=float]`: The wall clock time since player creation.
- `[mediaPos=float]`: The current playback position.
- `[window=int]`: The current window index.
- `[period=int]`: The current period in that window.

The final elements in each line indicate the value of the state being reported.

### Media tracks

Track information is logged when the available or selected tracks change. This
happens at least once at the start of playback. The following example shows
track logging for an adaptive stream:

    EventLogger: tracks [eventTime=0.30, mediaPos=0.00, window=0, period=0,
    EventLogger:   group [
    EventLogger:     [X] Track:0, id=133, mimeType=video/avc, bitrate=261112, codecs=avc1.4d4015, res=426x240, fps=30.0, supported=YES
    EventLogger:     [X] Track:1, id=134, mimeType=video/avc, bitrate=671331, codecs=avc1.4d401e, res=640x360, fps=30.0, supported=YES
    EventLogger:     [X] Track:2, id=135, mimeType=video/avc, bitrate=1204535, codecs=avc1.4d401f, res=854x480, fps=30.0, supported=YES
    EventLogger:     [X] Track:3, id=160, mimeType=video/avc, bitrate=112329, codecs=avc1.4d400c, res=256x144, fps=30.0, supported=YES
    EventLogger:     [ ] Track:4, id=136, mimeType=video/avc, bitrate=2400538, codecs=avc1.4d401f, res=1280x720, fps=30.0, supported=NO_EXCEEDS_CAPABILITIES
    EventLogger:   ]
    EventLogger:   group [
    EventLogger:     [ ] Track:0, id=139, mimeType=audio/mp4a-latm, bitrate=48582, codecs=mp4a.40.5, channels=2, sample_rate=22050, supported=YES
    EventLogger:     [X] Track:1, id=140, mimeType=audio/mp4a-latm, bitrate=127868, codecs=mp4a.40.2, channels=2, sample_rate=44100, supported=YES
    EventLogger:   ]
    EventLogger: ]

In this example, the player has selected four of the five available video
tracks. The fifth video track is not selected because it exceeds the
capabilities of the device, as indicated by `supported=NO_EXCEEDS_CAPABILITIES`.
The player adapts between the selected video tracks during playback. When
the player adapts from one track to another, it's logged in a line like the
following:

    EventLogger: downstreamFormat [eventTime=3.64, mediaPos=3.00, window=0, period=0, id=134, mimeType=video/avc, bitrate=671331, codecs=avc1.4d401e, res=640x360, fps=30.0]

This log line indicates that the player switched to the 640x360 resolution video
track three seconds into the media.

### Decoder selection

In most cases, ExoPlayer renders media using a `MediaCodec` acquired from the
underlying platform. When a decoder is initialized, this is logged in lines like
these:

    EventLogger: videoDecoderInitialized [0.77, 0.00, window=0, period=0, video, OMX.qcom.video.decoder.avc]
    EventLogger: audioDecoderInitialized [0.79, 0.00, window=0, period=0, audio, OMX.google.aac.decoder]