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

ExportLogsServiceRequest JSON example may be invalid #579

Open
demurgos opened this issue Aug 30, 2024 · 3 comments
Open

ExportLogsServiceRequest JSON example may be invalid #579

demurgos opened this issue Aug 30, 2024 · 3 comments

Comments

@demurgos
Copy link

demurgos commented Aug 30, 2024

I am writing serialization tests for Opentelemetry Rust, and working with the examoke JSON files in this repo.

I have concerns that the logs.json example may be invalid or out of date; or I may be missing something.

The example contains an attribute using an array of strings as values:

                {
                  "key": "array.attribute",
                  "value": {
                    "arrayValue": {
                      "values": [
                        {
                          "stringValue": "many"
                        },
                        {
                          "stringValue": "values"
                        }
                      ]
                    }
                  }
                }

The JSON above uses AnyValue for the array items, but in the protobuf specs I see ArrayValue which adds a layer of indirection (notice the extra "value" layer). I would expect the following JSON serialization:

                {
                  "key": "array.attribute",
                  "value": {
                    "arrayValue": {
                      "values": [
                        {
                          "value": {
                            "stringValue": "many"
                          }
                        },
                        {
                          "value": {
                            "stringValue": "values"
                          }
                        }
                      ]
                    }
                  }
                }
@tigrannajaryan
Copy link
Member

I think you are right. Can you please double check by sending the payload to the otlp receiver in the Collector?

@demurgos
Copy link
Author

demurgos commented Aug 30, 2024

I wrote a test program using Rust's OpenTelemetry SDK. The raw JSON payload is attached below. It uses the the variant with the extra {"value": ...} layer. Please note that I am not 100% confident in the correctness of Rust's exporter though (I was actually testing it when I stumbled upon the issue).

JSON payload
{
  "resourceLogs": [
    {
      "resource": {
        "attributes": [
          {
            "key": "service.name",
            "value": {
              "stringValue": "eternaltwin"
            }
          },
          {
            "key": "deployment.environment",
            "value": {
              "stringValue": "dev"
            }
          },
          {
            "key": "telemetry.sdk.version",
            "value": {
              "stringValue": "0.24.1"
            }
          },
          {
            "key": "telemetry.sdk.name",
            "value": {
              "stringValue": "opentelemetry"
            }
          },
          {
            "key": "telemetry.sdk.language",
            "value": {
              "stringValue": "rust"
            }
          },
          {
            "key": "service.version",
            "value": {
              "stringValue": "0.14.2"
            }
          }
        ],
        "droppedAttributesCount": 0
      },
      "scopeLogs": [
        {
          "scope": {
            "name": "test_logger",
            "version": "",
            "attributes": [],
            "droppedAttributesCount": 0
          },
          "logRecords": [
            {
              "timeUnixNano": "0",
              "observedTimeUnixNano": "1725057088789852647",
              "severityNumber": 0,
              "severityText": "",
              "body": null,
              "attributes": [
                {
                  "key": "test_array",
                  "value": {
                    "arrayValue": {
                      "values": [
                        {
                          "value": {
                            "stringValue": "foo"
                          }
                        },
                        {
                          "value": {
                            "stringValue": "bar"
                          }
                        }
                      ]
                    }
                  }
                }
              ],
              "droppedAttributesCount": 0,
              "flags": 0,
              "traceId": "",
              "spanId": ""
            }
          ],
          "schemaUrl": ""
        }
      ],
      "schemaUrl": ""
    }
  ]
}
Test program
    let logger_provider = SdkLoggerProvider::builder()
      .with_resource({
        let process = Resource::new(
          config
            .opentelemetry
            .attributes
            .value
            .iter()
            .map(|(key, value)| KeyValue::new(key.to_string(), value.value.to_string())),
        );
        let telemetry: Resource = TelemetryResourceDetector.detect(Duration::from_secs(0));
        Resource::merge(&telemetry, &process)
      })
      .with_batch_exporter(
        {
          let exporter = opentelemetry_otlp::new_exporter()
            .http()
            .with_endpoint("http://localhost:5080/")
            .with_timeout(Duration::from_secs(1))
            .with_http_client(HyperClient::default())
            .with_headers({
              let mut metadata: HashMap<String, String> = HashMap::new();
              metadata.insert(String::from("Authorization"), String::from("abc"));
              metadata
            });
          exporter.build_log_exporter().expect("exporter is valid")
        },
        opentelemetry_sdk::runtime::Tokio,
      )
      .build();

    let logger: SdkLogger = logger_provider.logger("test_logger");

    logger.emit({
      let mut r = logger.create_log_record();
      r.attributes = Some(vec![(
        String::from("test_array").into(),
        AnyValue::ListAny(vec![String::from("foo").into(), String::from("bar").into()]),
      )]);
      r
    });

@tigrannajaryan
Copy link
Member

Please note that I am not 100% confident in the correctness of Rust's exporter though (I was actually testing it when I stumbled upon the issue).

This is the reason I was suggesting to send to the Collector. We consider it the canonical implementation. Can you run a Collector with otlp receiver and debug exporter and send it this payload and confirm in the debug output that values are correctly received?

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

No branches or pull requests

2 participants