Docs: Your first logs
Documentation / Get started

Your first logs

Add OBSESC as a second destination in your log shipper, then confirm events are arriving and stored.

This page shows you how to add OBSESC to an existing shipper as an extra output, and how to check that events are arriving and being stored. You’ll need a deployed stack. If you don’t have one yet, start with the Quick start.

Throughout this page, obsesc.your-domain.internal stands for your node’s address: the private IP from the stack outputs, or a DNS name you’ve pointed at it.

Choose a protocol

If you run…Send toPortOpen by default?
OpenTelemetry Collector or SDKsOTLP/HTTP (protobuf) or OTLP/gRPC4318 / 4317Yes
Filebeat, Logstash, rsyslogElasticsearch _bulk9200Yes
Fluent Bit or FluentdFluent Forward24224No, add a security group rule
Splunk HTTP Event Collector (HEC) clientsSplunk HEC8088No, add a security group rule and set hec_tokens
VectorVector native (gRPC)9000No, add a security group rule

The OTLP/HTTP listener at /v1/logs accepts protobuf only. It rejects JSON-encoded OTLP with 415. The OpenTelemetry Collector’s otlphttp exporter sends protobuf by default.

Splunk support is through HEC only. OBSESC doesn’t receive the Splunk forwarder-to-indexer protocol.

For every supported source, see Supported sources.

Add OBSESC as a second output

In each example below, your existing destination stays exactly as it is. You only add a block.

OpenTelemetry Collector

exporters:
  otlphttp/obsesc:
    endpoint: http://obsesc.your-domain.internal:4318
    # Only needed when the node enforces ingest tokens:
    headers:
      authorization: "Bearer ${env:OBSESC_INGEST_TOKEN}"

service:
  pipelines:
    logs:
      receivers: [otlp]
      # Keep your existing exporter in the list, e.g. [otlphttp/obsesc, datadog]
      exporters: [otlphttp/obsesc]
    traces:
      receivers: [otlp]
      exporters: [otlphttp/obsesc]

The exporter adds /v1/logs and /v1/traces itself, so the endpoint is just the host and port. OBSESC stores every span as an event, so send it the unsampled trace stream and keep any sampling on your other exporter. See OpenTelemetry.

Filebeat

Filebeat supports only one output. If Filebeat already feeds your current platform, run a second Filebeat instance with this configuration, or split the stream further upstream.

filebeat.inputs:
  - type: filestream
    id: app-logs
    paths: [/var/log/app/*.log]
    parsers:
      - multiline:
          type: pattern
          pattern: '^\d{4}-\d{2}-\d{2}'
          negate: true
          match: after

output.elasticsearch:
  hosts: ["http://obsesc.your-domain.internal:9200"]
  allow_older_versions: true
  # When the node enforces ingest tokens:
  #api_key: "id:api_key"

setup.template.enabled: false
setup.ilm.enabled: false

With api_key, Filebeat sends Authorization: ApiKey <base64(id:api_key)>. The node compares that base64 string with its ingest token list, so add the same encoded value there. See Filebeat.

Fluent Bit

Fluent Bit uses the Forward protocol on port 24224. First, add an inbound rule for 24224 to the node’s security group.

[INPUT]
    Name              tail
    Path              /var/log/app/*.log
    Tag               app
    multiline.parser  java

[OUTPUT]
    Name           forward
    Match          *
    Host           obsesc.your-domain.internal
    Port           24224
    # When the node sets fluent_shared_key:
    #Shared_Key     ${OBSESC_FLUENT_SHARED_KEY}
    #Self_Hostname  my-host

The Fluent tag becomes the OBSESC service name, so use one tag per service. See Fluent Bit.

How OBSESC names services

Every event belongs to a service, and most views are organised by it. Where the service comes from depends on the protocol:

ProtocolService taken from
OTLPThe resource attribute service.name
Elasticsearch _bulkThe document’s service field, then service.name, then the _index on the action line
Fluent ForwardThe Fluent tag
Vector nativeA service field you set in a remap transform

Events without a service go into a single group called unknown. You can change that name with ingest.default_service, or name an attribute to use as the service with ingest.service_from, for example kubernetes.namespace_name. See the Configuration reference.

Assemble multi-line events in the shipper

OBSESC treats each record it receives as one event. A Java stack trace delivered as 30 lines becomes 30 events. Turn on multi-line handling in your shipper, as the examples above do:

  • Fluent Bit: multiline.parser
  • Filebeat: parsers: multiline
  • Vector: [sources.*.multiline]
  • OTel Collector filelog receiver: the recombine operator

If a source has no shipper stage that can do this, contact us.

Confirm events are arriving

1. Check the node is ready

curl -i http://obsesc.your-domain.internal:18080/ready

A 200 means the node is ready to accept and store data. A 503 means it isn’t, and the response says why.

2. Watch the live tail

curl -N "http://obsesc.your-domain.internal:18080/v1/tail?service=app&max_events=20"

Each event appears as the node accepts it. service limits the stream to one service, and max_events stops it after that many events. Ingest never slows down to wait for a tail client.

The tail shows events as they arrive, not stored data. An event can appear on the tail and still be refused afterwards, for example if it’s a duplicate or its batch is rejected. To confirm storage, use step 3.

If you’ve set AuthSecretArn, add -H "Authorization: Bearer <query_api_token>" to every /v1 request.

3. Query the stored raw events

Once events have been committed to your S3 bucket, you can query them with SQL:

curl -sS -X POST http://obsesc.your-domain.internal:18080/v1/sql \
  -H "Content-Type: application/json" \
  -d '{"sql": "SELECT timestamp_ns, service FROM raw_events ORDER BY timestamp_ns DESC LIMIT 10"}'

The response is JSON with a rows array. raw_events exposes timestamp_ns, service, body, an attributes map (queried as attributes['request_id']), and the first-class dimensions host, env, namespace and tenant. See the SQL reference.

Because the raw events are open Parquet files in your bucket, you can also query them with your own tools, such as Athena or DuckDB.

4. Check the console

Open the console at the UiUrl stack output (port 18080 on a default deployment). Your service appears once its events are stored, and the views that summarise history fill in a little later. See What happens next.

Troubleshooting first delivery

SymptomLikely cause
Connection refused or timed outThe source isn’t in AllowedIngestCidr, or the port (24224, 8088, 9000) isn’t open in the security group.
401 from ingestThe node enforces ingest tokens and the shipper isn’t sending a matching Authorization header.
415 on port 4318The shipper is sending OTLP as JSON. Switch it to protobuf.
All HEC requests rejectedhec_tokens isn’t set. HEC rejects every request until it is.
503 with Retry-AfterThe node is applying backpressure. Shippers should retry, and most do by default.
Events land under unknownThe shipper isn’t setting a service. See “How OBSESC names services” above.

For more, see Troubleshooting.