Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Loki exporter is not setting X-scoppe-OrgID(tenant id) based on log attribute (loki.tenant) #26557

Closed
sairamsadanala opened this issue Sep 8, 2023 · 11 comments
Labels
exporter/loki Loki Exporter

Comments

@sairamsadanala
Copy link

Component(s)

exporter/loki

What happened?

Description

I am setting up otelcol-contrib hub to receive telemetry(logs) from different sources and exporting them to loki adding tenant(X-Scope-OrgID) dynamically. Otelcol-contrib hub receives log.file.path: Str(/var/log/pods/_XXXX-sample-XX-default-1_d30d866a-b217-4d9a-a4c3-6dd8efb4a79a/XXX-XXX-XX-XXX/0.log) attribute and need to extract value from log.file.path attribute and set loki.tenant attribute while exporting logs to loki endpoint.

Steps to Reproduce

Expected Result

Loki exporter should set orgid if loki.tenant hint exist, while exporting logs to loki endpoint.

Actual Result

("error": "Permanent error: HTTP 401 "Unauthorized": no org id", "dropped_items": XX}.

Collector version

0.82.0

Environment information

Environment

OS: AWS Kubernetes

OpenTelemetry Collector configuration

exporters:
  logging:
    verbosity: detailed
  loki:
    endpoint: http://XXXXXXXXXXXXXXXX/loki/api/v1/push
    tls:
      insecure: false
      insecure_skip_verify: true
extensions:
  health_check:
    endpoint: 0.0.0.0:13133
processors:
  attributes:
    actions:
    - action: extract
      key: log.file.path
      pattern: \/var\/log\/pods\/(?P<loki_temp>[0-9a-z-]*)_.*
    - action: upsert
      from_attribute: loki_temp
      key: loki.tenant
    - action: delete
      key: loki_temp
  transform:
    error_mode: ignore
    log_statements:
    - context: log
      statements:
      - set(attributes["cache"], ParseJSON(body)) where IsMatch(body, "^\\{")
      - set(attributes["tenant"], attributes["cache"]["kubernetes"]["namespace_name"])
      - set(attributes["loki.tenant"], "tenant")
      - delete_key(attributes, "cache")
receivers:
  otlp:
    protocols:
      http:
        endpoint: 0.0.0.0:4318
        include_metadata: true

service:
  extensions:
  - health_check
  pipelines:
    logs:
      exporters:
      - logging
      - loki
      processors:
      - transform
      - attributes
      receivers:
      - otlp

Log output

attributes processed by Transform processor:

Body: Str({"timestamp": "2023-09-08T17:59:01.965505Z", "kubernetes": {"host": "XXXXXXX", "namespace_name": "XXXX-testing"}})
Attributes:
-> log.file.name: Str(mylog.log)
-> log.file.path: Str(/var/log/mylog.log)
-> loki.tenant: Str(tenant)
-> tenant: Str(XXXX-testing)
***************************************************************
attributes processed by Attributes processor:

Body: Str({"timestamp": "2023-09-08T18:05:01.580359Z", "kubernetes": {"host": "XXXXXXX"}})
Attributes:
-> log.file.name: Str(mylog.log)
-> log.file.path: Str(/var/log/pods/mynamespace_XXXX-sample-es-default-1_d30d866a-b217-4d9a-a4c3-6dd8efb4a79a/XXXXXXX/mylog.log)
-> loki.tenant: Str(mynamespace)

Additional context

it is using an attributes processor and a transform processor to extract Kubernetes namespace. Transform processor looks for log body and extract kubernetes namespace and set loki.tenant attribute, and the attributes processor extract namespace value from log.file.path attribute and set loki.tenant.

Otelcol-contrib able to send the logs to loki when the logs are processed by Transform processor but failing ("error": "Permanent error: HTTP 401 "Unauthorized": no org id", "dropped_items": XX} when logs are processed by Attributes processor. I believe it is because of the tenant value is missing as show above.

As per loki exporter documentation, If the loki.tenant hint attribute is present in both resource and log attributes, then the look-up for a tenant value from resource attributes takes precedence. It is working when the logs are processed by Transform but not in Attributes processor case. Am I missing anything here?

@sairamsadanala sairamsadanala added bug Something isn't working needs triage New item requiring triage labels Sep 8, 2023
@github-actions github-actions bot added the exporter/loki Loki Exporter label Sep 8, 2023
@github-actions
Copy link
Contributor

github-actions bot commented Sep 8, 2023

Pinging code owners:

See Adding Labels via Comments if you do not have permissions to add labels yourself.

@jpkrohling
Copy link
Member

I was able to get it working with a local Loki. What's your remote like? Is it Grafana Cloud Logs? Here's what I did:

> docker run -d --rm --name=loki -p 3100:3100 grafana/loki
> logcli query -q --org-id=tenant '{exporter="OTLP"}'
> otelcol-contrib --config debug-26557.yaml
> telemetrygen logs --otlp-insecure --body "some message about logging something very very important"
> logcli query -q --org-id=tenant '{exporter="OTLP"}'
2023-09-11T06:19:24-03:00 {} {"body":"some message about logging something very very important","severity":"Info","attributes":{"app":"server"}}

Here's my collector config:

receivers:
  otlp:
    protocols:
      grpc:

processors:
  transform:
    error_mode: ignore
    log_statements:
    - context: log
      statements:
      - set(attributes["loki.tenant"], "tenant")

exporters:
  logging:
    verbosity: detailed
  loki:
    endpoint: http://localhost:3100/loki/api/v1/push

service:
  pipelines:
    logs:
      receivers: [otlp]
      processors: [transform]
      exporters: [logging, loki]

@sairamsadanala
Copy link
Author

I am using loki endpoint running on AWS EKS. It is working for the logs that were being processed by transform processor (extracting lokt.tenant) but it is not working for Attributes processor.

attributes processed by Transform processor:

Body: Str({"timestamp": "2023-09-08T17:59:01.965505Z", "kubernetes": {"host": "XXXXXXX", "namespace_name": "XXXX-testing"}})
Attributes:
-> log.file.name: Str(mylog.log)
-> log.file.path: Str(/var/log/mylog.log)
-> loki.tenant: Str(tenant)
-> tenant: Str(XXXX-testing)


attributes processed by Attributes processor:

Body: Str({"timestamp": "2023-09-08T18:05:01.580359Z", "kubernetes": {"host": "XXXXXXX"}})
Attributes:
-> log.file.name: Str(mylog.log)
-> log.file.path: Str(/var/log/pods/mynamespace_XXXX-sample-es-default-1_d30d866a-b217-4d9a-a4c3-6dd8efb4a79a/XXXXXXX/mylog.log)
-> loki.tenant: Str(mynamespace)

@sairamsadanala
Copy link
Author

sairamsadanala commented Sep 11, 2023

error - log output


LogRecord #0
ObservedTimestamp: 2023-09-11 12:53:30.434742722 +0000 UTC
Timestamp: 2023-09-11 12:53:30.412745803 +0000 UTC
SeverityText:
SeverityNumber: Unspecified(0)
Body: Str(2023-09-11T12:53:30.412745803+00:00 stdout F [2023-09-11T12:53:30.412+00:00][INFO ][plugins.fleet] Running Fleet Usage telemetry send task)
Attributes:
-> log.file.path: Str(/var/log/pods/mytenantname_XXXXXX-sample-kb-rwer67677-gh16nv_584ba49b-fc94-4d6b-b9f9-599d3ccdfbb7/kibana/0.log)
-> logtag: Str(F)
-> log: Str([2023-09-11T12:53:30.412+00:00][INFO ][plugins.fleet] Running Fleet Usage telemetry send task)
-> time: Str(2023-09-11T12:53:30.412745803+00:00)
-> log.iostream: Str(stdout)
-> loki.tenant: Str(mytenantname)
Trace ID:
Span ID:
Flags: 0
{"kind": "exporter", "data_type": "logs", "name": "logging"}
2023-09-11T12:53:30.567Z error exporterhelper/queued_retry.go:391 Exporting failed. The error is not retryable. Dropping data. {"kind": "exporter", "data_type": "logs", "name": "loki", "error": "Permanent error: HTTP 401 "Unauthorized": no org id", "dropped_items": 1}

@jpkrohling
Copy link
Member

This isn't about the Loki exporter then, right? Your output shows the tenant for the attributes processor to be set to "mynamespace". You seem to have a configuration problem with the attributes processor instead, but perhaps I'm still missing something?

What's the expected value for the tenant when using the attributes processor?

@sairamsadanala
Copy link
Author

expected value for tenant is "mytenantname" which is happening as shown above (loki.tenant: Str(mytenantname)).
As per loki exporter,If the loki.tenant hint attribute is present either in resource or log attributes, loki exporter should set orgid from log attribute and export to endpoint. However, in my case, loki exporter is not setting orgid while exporting logs to endpoint even though loki.teanant log attribute hint is available. As a result of this getting 401 (no orgid). Please let me know if you need any further details.

@jpkrohling
Copy link
Member

Something didn't seem right with my previous example, and I found out that I was running Loki with no auth. I'm not sure how I got an empty result for the first check, but I think I found the source of confusion of this ticket: the value for the loki.tenant attribute is the name of the attribute that holds the tenant information. Like this:

receivers:
  otlp:
    protocols:
      grpc:

processors:
  transform:
    error_mode: ignore
    log_statements:
    - context: log
      statements:
      - set(attributes["tenant"], "my-tenant")
      - set(attributes["loki.tenant"], "tenant")
      - set(resource.attributes["restenant"], "my-restenant")
      - set(resource.attributes["loki.tenant"], "restenant")

exporters:
  logging:
    verbosity: detailed
  loki:
    endpoint: http://localhost:3100/loki/api/v1/push

service:
  pipelines:
    logs:
      receivers: [otlp]
      processors: [transform]
      exporters: [logging, loki]

In this example, the tenant will be set to "my-restenant", taken from the resource attribute "restenant". In your case, either use the header setter extension to use the value mytenantname as the source of information, or store it on another attribute and reference that via loki.tenant.

@mar4uk
Copy link
Contributor

mar4uk commented Sep 11, 2023

Agree with Juraci.
Your configuration of the attributes processor should work correctly if you remove the last action:

- action: delete
   key: loki_temp

That would fulfill the second Juraci's proposal: store it on another attribute and reference that via loki.tenant.

@sairamsadanala
Copy link
Author

sairamsadanala commented Sep 11, 2023

thanks @mar4uk @jpkrohling.

I have removed the suggested change..

My config file


exporters:
  logging:
    verbosity: detailed
  loki:
    endpoint: http://lXXXXXXXXXXX/loki/api/v1/push
    retry_on_failure:
      enabled: true
      initial_interval: 1s
      max_elapsed_time: 120s
      max_interval: 300s
    sending_queue:
      storage: file_storage/psq
    tls:
      insecure: false
      insecure_skip_verify: true
extensions:
  basicauth/server:
    htpasswd:
      inline: |
        XXXX:XXXXX
  file_storage/psq:
    compaction:
      max_transaction_size: 65536
      on_start: true
    directory: /var/lib/otelcol/file_storage
    timeout: 1s
  health_check:
    endpoint: 0.0.0.0:13133
  memory_ballast:
    size_in_percentage: 40
  pprof:
    endpoint: 0.0.0.0:1777
  zpages:
    endpoint: 0.0.0.0:55679
processors:
  attributes:
    actions:
    - action: extract
      key: log.file.path
      pattern: \/var\/log\/pods\/(?P<loki_temp>[0-9a-z-]*)_.*
    - action: upsert
      from_attribute: loki_temp
      key: loki.tenant
  transform:
    error_mode: ignore
    log_statements:
    - context: log
      statements:
      - set(attributes["cache"], ParseJSON(body)) where IsMatch(body, "^\\{")
      - set(attributes["tenant"], attributes["cache"]["kubernetes"]["namespace_name"])
      - set(attributes["loki.tenant"], "tenant")
      - delete_key(attributes, "cache")
receivers:
  loki:
    protocols:
      grpc: null
      http: null
    use_incoming_timestamp: true
  otlp:
    protocols:
      http:
        auth:
          authenticator: basicauth/server
        endpoint: 0.0.0.0:4318
        include_metadata: true
service:
  extensions:
  - health_check
  - pprof	
  - zpages
  - memory_ballast
  - file_storage/psq
  - basicauth/server
  pipelines:
    logs:
      exporters:
      - logging	
      - loki
      processors:
      - memory_limiter
      - transform
      - attributes
      receivers:
      - otlp

I am stilling getting the same error [401 unauthorized no orgid].

: Str({"timestamp": "2023-09-11T17:20:01.525299Z", "kubernetes": {"host": "XXXXXXXXXXXX"}})
Attributes:
     -> log.file.name: Str(mylog.log)
     -> log.file.path: Str(/var/log/pods/XXelasticsearch_elasticsearch-sample-es-default-1_d30d866a-b217-4d9a-a4c3-6dd8efb4a79a/elasticsearch/mylog.log)
     -> loki_temp: Str(XXelasticsearch)
     -> loki.tenant: Str(XXelasticsearch)
Trace ID:
Span ID:
Flags: 0
        {"kind": "exporter", "data_type": "logs", "name": "logging"}
2023-09-11T17:20:01.655Z        error   exporterhelper/queued_retry.go:391      Exporting failed. The error is not retryable. Dropping data.  {"kind": "exporter", "data_type": "logs", "name": "loki", "error": "Permanent 
error: HTTP 401 \"Unauthorized\": no org id", "dropped_items": 10}

  1. I also tried without Transform processor and same error
  2. Added resource attribute to set loki.tenant hint along with log attributes but no luck.
    resource:
      attributes:
      - key: loki.tenant
        from_attribute: loki_temp 
        action: upsert

Am I missing anything here?

are there any conflicts using Transform and Attributes processor together to set loki.tenant hint? It is working fine with Transform processor case but not with Attributes case. Is there way we can use Transform Processor to extract value from log.file.path attribute and set loki.enant hint?

@mar4uk
Copy link
Contributor

mar4uk commented Sep 12, 2023

o, I got it.
Here is a correct config:

processors:
  attributes:
    actions:
      - action: extract
        key: log.file.path
        pattern: \/var\/log\/pods\/(?P<loki_temp>[0-9a-z-]*)_.*
      - action: upsert
        value: loki_temp
        key: loki.tenant

you should use value instead of from_attribute. The loki.tenant attribute value should be equal to the name of the attribute that stores the value for X-Scope-ID.
The collector with this config produces a log record:

Resource SchemaURL: 
Resource attributes:
     -> my-attr: Str(foo7)
ScopeLogs #0
ScopeLogs SchemaURL: 
InstrumentationScope  1
LogRecord #0
ObservedTimestamp: 1970-01-01 00:00:00 +0000 UTC
Timestamp: 2023-09-12 08:14:28 +0000 UTC
SeverityText: 
SeverityNumber: Unspecified(0)
Body: Str(hello)
Attributes:
     -> log.file.path: Str(/var/log/pods/mynamespace_XXXX-sample-es-default-1_d30d866a-b217-4d9a-a4c3-6dd8efb4a79a/XXXXXXX/mylog.log)
     -> loki_temp: Str(mynamespace)
     -> loki.tenant: Str(loki_temp)
Trace ID: 
Span ID: 
Flags: 0
        {"kind": "exporter", "data_type": "logs", "name": "logging"}

See loki.tenant attribute value is equal to the name of the attribute that contains the desired value loki_temp

@sairamsadanala
Copy link
Author

Thanks @mar4uk @jpkrohling.. My apologies for the delayed response. It solved my issue and thanks a ton again,

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
exporter/loki Loki Exporter
Projects
None yet
Development

No branches or pull requests

4 participants