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

[Metricbeat] Convert millis-since-epoch timestamps in elasticsearch/ml_job metricset to ints #14222

Merged
merged 5 commits into from
Oct 28, 2019

Conversation

ycombinator
Copy link
Contributor

@ycombinator ycombinator commented Oct 24, 2019

Resolves #14220.

The elasticsearch/ml_job metricset calls the GET "/anomaly_detectors/_all/_stats Elasticsearch API to collect monitoring metrics about ML jobs running in Elasticsearch. This API's response contains several fields that are timestamps represented as milliseconds-since-epoch; see https://www.elastic.co/guide/en/elasticsearch/reference/current/ml-get-job-stats.html#ml-get-job-stats-example.

Of these fields, two are actually indexed in .monitoring-es-*: job_stats.data_counts.earliest_record_timestamp and job_stats.data_counts.latest_record_timestamp.

As the mappings indicate, these fields are of type: "date". Per elastic/elasticsearch#36691, the Elasticsearch date parser can no longer accept millis-since-epoch values in scientific notation (e.g. 1.571647285959e+12). However, during the unmarshalling of the ML API response JSON into memory, the json.Unmarshal function will, by default, produce float64 values. These values, when marshalled back into JSON for indexing into Elasticsearch may be represented in scientific notation if they are sufficiently large, which will be rejected by the Elasticsearch date parser with an error like so:

```
[2019-10-17T13:00:44,628][DEBUG][o.e.a.b.TransportShardBulkAction] [node-1] [.monitoring-es-7-mb-2019.10.17][0] failed to execute bulk item (index) index {[.monitoring-es-7-mb-2019.10.17][_doc][csbg120B1fyMIM-CAGdJ], source[n/a, actual length: [2.8kb], max length: 2kb]}
org.elasticsearch.index.mapper.MapperParsingException: failed to parse field [job_stats.data_counts.latest_record_timestamp] of type [date] in document with id 'csbg120B1fyMIM-CAGdJ'. Preview of field's value: '1.571284349E12'
        at org.elasticsearch.index.mapper.FieldMapper.parse(FieldMapper.java:299) ~[elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.index.mapper.DocumentParser.parseObjectOrField(DocumentParser.java:488) ~[elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.index.mapper.DocumentParser.parseValue(DocumentParser.java:614) ~[elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.index.mapper.DocumentParser.innerParseObject(DocumentParser.java:427) ~[elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.index.mapper.DocumentParser.parseObjectOrNested(DocumentParser.java:395) ~[elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.index.mapper.DocumentParser.parseObjectOrField(DocumentParser.java:485) ~[elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.index.mapper.DocumentParser.parseObject(DocumentParser.java:505) ~[elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.index.mapper.DocumentParser.innerParseObject(DocumentParser.java:418) ~[elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.index.mapper.DocumentParser.parseObjectOrNested(DocumentParser.java:395) ~[elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.index.mapper.DocumentParser.parseObjectOrField(DocumentParser.java:485) ~[elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.index.mapper.DocumentParser.parseObject(DocumentParser.java:505) ~[elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.index.mapper.DocumentParser.innerParseObject(DocumentParser.java:418) ~[elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.index.mapper.DocumentParser.parseObjectOrNested(DocumentParser.java:395) ~[elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.index.mapper.DocumentParser.internalParseDocument(DocumentParser.java:112) ~[elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.index.mapper.DocumentParser.parseDocument(DocumentParser.java:71) ~[elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.index.mapper.DocumentMapper.parse(DocumentMapper.java:267) ~[elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.index.shard.IndexShard.prepareIndex(IndexShard.java:776) ~[elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.index.shard.IndexShard.applyIndexOperation(IndexShard.java:753) ~[elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.index.shard.IndexShard.applyIndexOperationOnPrimary(IndexShard.java:725) ~[elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.action.bulk.TransportShardBulkAction.executeBulkItemRequest(TransportShardBulkAction.java:258) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.action.bulk.TransportShardBulkAction$2.doRun(TransportShardBulkAction.java:161) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.common.util.concurrent.AbstractRunnable.run(AbstractRunnable.java:37) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.action.bulk.TransportShardBulkAction.performOnPrimary(TransportShardBulkAction.java:193) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.action.bulk.TransportShardBulkAction.shardOperationOnPrimary(TransportShardBulkAction.java:118) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.action.bulk.TransportShardBulkAction.shardOperationOnPrimary(TransportShardBulkAction.java:79) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.action.support.replication.TransportReplicationAction$PrimaryShardReference.perform(TransportReplicationAction.java:917) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.action.support.replication.ReplicationOperation.execute(ReplicationOperation.java:108) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.action.support.replication.TransportReplicationAction$AsyncPrimaryAction.runWithPrimaryShardReference(TransportReplicationAction.java:394) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.action.support.replication.TransportReplicationAction$AsyncPrimaryAction.lambda$doRun$0(TransportReplicationAction.java:316) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.action.ActionListener$1.onResponse(ActionListener.java:62) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.index.shard.IndexShard.lambda$wrapPrimaryOperationPermitListener$21(IndexShard.java:2753) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.action.ActionListener$3.onResponse(ActionListener.java:112) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.index.shard.IndexShardOperationPermits.acquire(IndexShardOperationPermits.java:285) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.index.shard.IndexShardOperationPermits.acquire(IndexShardOperationPermits.java:237) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.index.shard.IndexShard.acquirePrimaryOperationPermit(IndexShard.java:2727) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.action.support.replication.TransportReplicationAction.acquirePrimaryOperationPermit(TransportReplicationAction.java:858) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.action.support.replication.TransportReplicationAction$AsyncPrimaryAction.doRun(TransportReplicationAction.java:312) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.common.util.concurrent.AbstractRunnable.run(AbstractRunnable.java:37) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.action.support.replication.TransportReplicationAction.handlePrimaryRequest(TransportReplicationAction.java:275) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.xpack.security.transport.SecurityServerTransportInterceptor$ProfileSecuredRequestHandler$1.doRun(SecurityServerTransportInterceptor.java:257) [x-pack-security-7.4.0.jar:7.4.0]
        at org.elasticsearch.common.util.concurrent.AbstractRunnable.run(AbstractRunnable.java:37) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.common.util.concurrent.EsExecutors$DirectExecutorService.execute(EsExecutors.java:225) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.xpack.security.transport.SecurityServerTransportInterceptor$ProfileSecuredRequestHandler.lambda$messageReceived$0(SecurityServerTransportInterceptor.java:306) [x-pack-security-7.4.0.jar:7.4.0]
        at org.elasticsearch.action.ActionListener$1.onResponse(ActionListener.java:62) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.xpack.security.authz.AuthorizationService.lambda$runRequestInterceptors$15(AuthorizationService.java:342) [x-pack-security-7.4.0.jar:7.4.0]
        at org.elasticsearch.action.ActionListener$1.onResponse(ActionListener.java:62) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.common.util.concurrent.ListenableFuture$1.doRun(ListenableFuture.java:99) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.common.util.concurrent.AbstractRunnable.run(AbstractRunnable.java:37) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.common.util.concurrent.EsExecutors$DirectExecutorService.execute(EsExecutors.java:225) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.common.util.concurrent.ListenableFuture.notifyListener(ListenableFuture.java:93) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.common.util.concurrent.ListenableFuture.lambda$done$0(ListenableFuture.java:85) [elasticsearch-7.4.0.jar:7.4.0]
        at java.util.ArrayList.forEach(ArrayList.java:1507) [?:?]
        at org.elasticsearch.common.util.concurrent.ListenableFuture.done(ListenableFuture.java:85) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.common.util.concurrent.BaseFuture.set(BaseFuture.java:144) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.common.util.concurrent.ListenableFuture.onResponse(ListenableFuture.java:114) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.action.StepListener.innerOnResponse(StepListener.java:62) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.action.NotifyOnceListener.onResponse(NotifyOnceListener.java:40) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.xpack.security.authz.interceptor.ResizeRequestInterceptor.intercept(ResizeRequestInterceptor.java:82) [x-pack-security-7.4.0.jar:7.4.0]
        at org.elasticsearch.xpack.security.authz.AuthorizationService.lambda$runRequestInterceptors$14(AuthorizationService.java:337) [x-pack-security-7.4.0.jar:7.4.0]
        at org.elasticsearch.action.ActionListener$1.onResponse(ActionListener.java:62) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.common.util.concurrent.ListenableFuture$1.doRun(ListenableFuture.java:99) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.common.util.concurrent.AbstractRunnable.run(AbstractRunnable.java:37) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.common.util.concurrent.EsExecutors$DirectExecutorService.execute(EsExecutors.java:225) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.common.util.concurrent.ListenableFuture.notifyListener(ListenableFuture.java:93) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.common.util.concurrent.ListenableFuture.lambda$done$0(ListenableFuture.java:85) [elasticsearch-7.4.0.jar:7.4.0]
        at java.util.ArrayList.forEach(ArrayList.java:1507) [?:?]
        at org.elasticsearch.common.util.concurrent.ListenableFuture.done(ListenableFuture.java:85) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.common.util.concurrent.BaseFuture.set(BaseFuture.java:144) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.common.util.concurrent.ListenableFuture.onResponse(ListenableFuture.java:114) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.action.StepListener.innerOnResponse(StepListener.java:62) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.action.NotifyOnceListener.onResponse(NotifyOnceListener.java:40) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.xpack.security.authz.interceptor.IndicesAliasesRequestInterceptor.intercept(IndicesAliasesRequestInterceptor.java:102) [x-pack-security-7.4.0.jar:7.4.0]
        at org.elasticsearch.xpack.security.authz.AuthorizationService.lambda$runRequestInterceptors$14(AuthorizationService.java:337) [x-pack-security-7.4.0.jar:7.4.0]
        at org.elasticsearch.action.ActionListener$1.onResponse(ActionListener.java:62) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.common.util.concurrent.ListenableFuture$1.doRun(ListenableFuture.java:99) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.common.util.concurrent.AbstractRunnable.run(AbstractRunnable.java:37) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.common.util.concurrent.EsExecutors$DirectExecutorService.execute(EsExecutors.java:225) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.common.util.concurrent.ListenableFuture.notifyListener(ListenableFuture.java:93) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.common.util.concurrent.ListenableFuture.lambda$done$0(ListenableFuture.java:85) [elasticsearch-7.4.0.jar:7.4.0]
        at java.util.ArrayList.forEach(ArrayList.java:1507) [?:?]
        at org.elasticsearch.common.util.concurrent.ListenableFuture.done(ListenableFuture.java:85) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.common.util.concurrent.BaseFuture.set(BaseFuture.java:144) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.common.util.concurrent.ListenableFuture.onResponse(ListenableFuture.java:114) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.action.StepListener.innerOnResponse(StepListener.java:62) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.action.NotifyOnceListener.onResponse(NotifyOnceListener.java:40) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.xpack.security.authz.interceptor.FieldAndDocumentLevelSecurityRequestInterceptor.intercept(FieldAndDocumentLevelSecurityRequestInterceptor.java:61) [x-pack-security-7.4.0.jar:7.4.0]
        at org.elasticsearch.xpack.security.authz.interceptor.SearchRequestInterceptor.intercept(SearchRequestInterceptor.java:19) [x-pack-security-7.4.0.jar:7.4.0]
        at org.elasticsearch.xpack.security.authz.AuthorizationService.lambda$runRequestInterceptors$14(AuthorizationService.java:337) [x-pack-security-7.4.0.jar:7.4.0]
        at org.elasticsearch.action.ActionListener$1.onResponse(ActionListener.java:62) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.common.util.concurrent.ListenableFuture$1.doRun(ListenableFuture.java:99) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.common.util.concurrent.AbstractRunnable.run(AbstractRunnable.java:37) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.common.util.concurrent.EsExecutors$DirectExecutorService.execute(EsExecutors.java:225) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.common.util.concurrent.ListenableFuture.notifyListener(ListenableFuture.java:93) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.common.util.concurrent.ListenableFuture.lambda$done$0(ListenableFuture.java:85) [elasticsearch-7.4.0.jar:7.4.0]
        at java.util.ArrayList.forEach(ArrayList.java:1507) [?:?]
        at org.elasticsearch.common.util.concurrent.ListenableFuture.done(ListenableFuture.java:85) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.common.util.concurrent.BaseFuture.set(BaseFuture.java:144) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.common.util.concurrent.ListenableFuture.onResponse(ListenableFuture.java:114) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.action.StepListener.innerOnResponse(StepListener.java:62) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.action.NotifyOnceListener.onResponse(NotifyOnceListener.java:40) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.xpack.security.authz.interceptor.FieldAndDocumentLevelSecurityRequestInterceptor.intercept(FieldAndDocumentLevelSecurityRequestInterceptor.java:61) [x-pack-security-7.4.0.jar:7.4.0]
        at org.elasticsearch.xpack.security.authz.interceptor.UpdateRequestInterceptor.intercept(UpdateRequestInterceptor.java:23) [x-pack-security-7.4.0.jar:7.4.0]
        at org.elasticsearch.xpack.security.authz.AuthorizationService.lambda$runRequestInterceptors$14(AuthorizationService.java:337) [x-pack-security-7.4.0.jar:7.4.0]
        at org.elasticsearch.action.ActionListener$1.onResponse(ActionListener.java:62) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.common.util.concurrent.ListenableFuture$1.doRun(ListenableFuture.java:99) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.common.util.concurrent.AbstractRunnable.run(AbstractRunnable.java:37) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.common.util.concurrent.EsExecutors$DirectExecutorService.execute(EsExecutors.java:225) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.common.util.concurrent.ListenableFuture.notifyListener(ListenableFuture.java:93) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.common.util.concurrent.ListenableFuture.lambda$done$0(ListenableFuture.java:85) [elasticsearch-7.4.0.jar:7.4.0]
        at java.util.ArrayList.forEach(ArrayList.java:1507) [?:?]
        at org.elasticsearch.common.util.concurrent.ListenableFuture.done(ListenableFuture.java:85) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.common.util.concurrent.BaseFuture.set(BaseFuture.java:144) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.common.util.concurrent.ListenableFuture.onResponse(ListenableFuture.java:114) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.action.StepListener.innerOnResponse(StepListener.java:62) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.action.NotifyOnceListener.onResponse(NotifyOnceListener.java:40) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.xpack.security.authz.interceptor.BulkShardRequestInterceptor.intercept(BulkShardRequestInterceptor.java:71) [x-pack-security-7.4.0.jar:7.4.0]
        at org.elasticsearch.xpack.security.authz.AuthorizationService.runRequestInterceptors(AuthorizationService.java:343) [x-pack-security-7.4.0.jar:7.4.0]
        at org.elasticsearch.xpack.security.authz.AuthorizationService.handleIndexActionAuthorizationResult(AuthorizationService.java:320) [x-pack-security-7.4.0.jar:7.4.0]
        at org.elasticsearch.xpack.security.authz.AuthorizationService.lambda$authorizeAction$9(AuthorizationService.java:261) [x-pack-security-7.4.0.jar:7.4.0]
        at org.elasticsearch.xpack.security.authz.AuthorizationService$AuthorizationResultListener.onResponse(AuthorizationService.java:613) [x-pack-security-7.4.0.jar:7.4.0]
        at org.elasticsearch.xpack.security.authz.AuthorizationService$AuthorizationResultListener.onResponse(AuthorizationService.java:588) [x-pack-security-7.4.0.jar:7.4.0]
        at org.elasticsearch.action.support.ContextPreservingActionListener.onResponse(ContextPreservingActionListener.java:43) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.xpack.security.authz.RBACEngine.buildIndicesAccessControl(RBACEngine.java:507) [x-pack-security-7.4.0.jar:7.4.0]
        at org.elasticsearch.xpack.security.authz.RBACEngine.lambda$authorizeIndexAction$3(RBACEngine.java:298) [x-pack-security-7.4.0.jar:7.4.0]
        at org.elasticsearch.action.ActionListener$1.onResponse(ActionListener.java:62) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.xpack.security.authz.AuthorizationService$CachingAsyncSupplier.lambda$getAsync$0(AuthorizationService.java:650) [x-pack-security-7.4.0.jar:7.4.0]
        at org.elasticsearch.action.ActionListener$1.onResponse(ActionListener.java:62) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.xpack.security.authz.AuthorizationService.resolveIndexNames(AuthorizationService.java:551) [x-pack-security-7.4.0.jar:7.4.0]
        at org.elasticsearch.xpack.security.authz.AuthorizationService.lambda$authorizeAction$6(AuthorizationService.java:249) [x-pack-security-7.4.0.jar:7.4.0]
        at org.elasticsearch.action.ActionListener$1.onResponse(ActionListener.java:62) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.xpack.security.authz.AuthorizationService$CachingAsyncSupplier.lambda$getAsync$0(AuthorizationService.java:650) [x-pack-security-7.4.0.jar:7.4.0]
        at org.elasticsearch.action.ActionListener$1.onResponse(ActionListener.java:62) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.xpack.security.authz.RBACEngine.loadAuthorizedIndices(RBACEngine.java:329) [x-pack-security-7.4.0.jar:7.4.0]
        at org.elasticsearch.xpack.security.authz.AuthorizationService.lambda$authorizeAction$5(AuthorizationService.java:245) [x-pack-security-7.4.0.jar:7.4.0]
        at org.elasticsearch.xpack.security.authz.AuthorizationService$CachingAsyncSupplier.getAsync(AuthorizationService.java:648) [x-pack-security-7.4.0.jar:7.4.0]
        at org.elasticsearch.xpack.security.authz.AuthorizationService.lambda$authorizeAction$8(AuthorizationService.java:248) [x-pack-security-7.4.0.jar:7.4.0]
        at org.elasticsearch.xpack.security.authz.AuthorizationService$CachingAsyncSupplier.getAsync(AuthorizationService.java:648) [x-pack-security-7.4.0.jar:7.4.0]
        at org.elasticsearch.xpack.security.authz.RBACEngine.lambda$authorizeIndexAction$4(RBACEngine.java:290) [x-pack-security-7.4.0.jar:7.4.0]
        at org.elasticsearch.action.ActionListener$1.onResponse(ActionListener.java:62) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.xpack.security.authz.RBACEngine.authorizeIndexActionName(RBACEngine.java:314) [x-pack-security-7.4.0.jar:7.4.0]
        at org.elasticsearch.xpack.security.authz.RBACEngine.authorizeIndexAction(RBACEngine.java:287) [x-pack-security-7.4.0.jar:7.4.0]
        at org.elasticsearch.xpack.security.authz.AuthorizationService.authorizeAction(AuthorizationService.java:259) [x-pack-security-7.4.0.jar:7.4.0]
        at org.elasticsearch.xpack.security.authz.AuthorizationService.maybeAuthorizeRunAs(AuthorizationService.java:225) [x-pack-security-7.4.0.jar:7.4.0]
        at org.elasticsearch.xpack.security.authz.AuthorizationService.lambda$authorize$1(AuthorizationService.java:191) [x-pack-security-7.4.0.jar:7.4.0]
        at org.elasticsearch.action.ActionListener$1.onResponse(ActionListener.java:62) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.action.support.ContextPreservingActionListener.onResponse(ContextPreservingActionListener.java:43) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.xpack.security.authz.RBACEngine.lambda$resolveAuthorizationInfo$1(RBACEngine.java:117) [x-pack-security-7.4.0.jar:7.4.0]
        at org.elasticsearch.action.ActionListener$1.onResponse(ActionListener.java:62) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.xpack.security.authz.store.CompositeRolesStore.getRoles(CompositeRolesStore.java:229) [x-pack-security-7.4.0.jar:7.4.0]
        at org.elasticsearch.xpack.security.authz.RBACEngine.getRoles(RBACEngine.java:123) [x-pack-security-7.4.0.jar:7.4.0]
        at org.elasticsearch.xpack.security.authz.RBACEngine.resolveAuthorizationInfo(RBACEngine.java:111) [x-pack-security-7.4.0.jar:7.4.0]
        at org.elasticsearch.xpack.security.authz.AuthorizationService.authorize(AuthorizationService.java:193) [x-pack-security-7.4.0.jar:7.4.0]
        at org.elasticsearch.xpack.security.transport.ServerTransportFilter$NodeProfile.lambda$inbound$1(ServerTransportFilter.java:130) [x-pack-security-7.4.0.jar:7.4.0]
        at org.elasticsearch.action.ActionListener$1.onResponse(ActionListener.java:62) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.xpack.security.authc.AuthenticationService$Authenticator.lambda$authenticateAsync$2(AuthenticationService.java:246) [x-pack-security-7.4.0.jar:7.4.0]
        at org.elasticsearch.xpack.security.authc.AuthenticationService$Authenticator.lambda$lookForExistingAuthentication$6(AuthenticationService.java:306) [x-pack-security-7.4.0.jar:7.4.0]
        at org.elasticsearch.xpack.security.authc.AuthenticationService$Authenticator.lookForExistingAuthentication(AuthenticationService.java:317) [x-pack-security-7.4.0.jar:7.4.0]
        at org.elasticsearch.xpack.security.authc.AuthenticationService$Authenticator.authenticateAsync(AuthenticationService.java:244) [x-pack-security-7.4.0.jar:7.4.0]
        at org.elasticsearch.xpack.security.authc.AuthenticationService$Authenticator.access$000(AuthenticationService.java:196) [x-pack-security-7.4.0.jar:7.4.0]
        at org.elasticsearch.xpack.security.authc.AuthenticationService.authenticate(AuthenticationService.java:139) [x-pack-security-7.4.0.jar:7.4.0]
        at org.elasticsearch.xpack.security.transport.ServerTransportFilter$NodeProfile.inbound(ServerTransportFilter.java:121) [x-pack-security-7.4.0.jar:7.4.0]
        at org.elasticsearch.xpack.security.transport.SecurityServerTransportInterceptor$ProfileSecuredRequestHandler.messageReceived(SecurityServerTransportInterceptor.java:313) [x-pack-security-7.4.0.jar:7.4.0]
        at org.elasticsearch.transport.RequestHandlerRegistry.processMessageReceived(RequestHandlerRegistry.java:63) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.transport.TransportService$7.doRun(TransportService.java:752) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.common.util.concurrent.ThreadContext$ContextPreservingAbstractRunnable.doRun(ThreadContext.java:773) [elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.common.util.concurrent.AbstractRunnable.run(AbstractRunnable.java:37) [elasticsearch-7.4.0.jar:7.4.0]
        at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) [?:?]
        at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) [?:?]
        at java.lang.Thread.run(Thread.java:830) [?:?]
Caused by: java.lang.IllegalArgumentException: failed to parse date field [1.571284349e+12] with format [strict_date_optional_time||epoch_millis]
        at org.elasticsearch.common.time.JavaDateFormatter.parse(JavaDateFormatter.java:123) ~[elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.index.mapper.DateFieldMapper$DateFieldType.parse(DateFieldMapper.java:331) ~[elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.index.mapper.DateFieldMapper.parseCreateField(DateFieldMapper.java:538) ~[elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.index.mapper.FieldMapper.parse(FieldMapper.java:277) ~[elasticsearch-7.4.0.jar:7.4.0]
        ... 168 more
Caused by: java.time.format.DateTimeParseException: Failed to parse with all enclosed parsers
        at org.elasticsearch.common.time.JavaDateFormatter.doParse(JavaDateFormatter.java:150) ~[elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.common.time.JavaDateFormatter.parse(JavaDateFormatter.java:121) ~[elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.index.mapper.DateFieldMapper$DateFieldType.parse(DateFieldMapper.java:331) ~[elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.index.mapper.DateFieldMapper.parseCreateField(DateFieldMapper.java:538) ~[elasticsearch-7.4.0.jar:7.4.0]
        at org.elasticsearch.index.mapper.FieldMapper.parse(FieldMapper.java:277) ~[elasticsearch-7.4.0.jar:7.4.0]
        ... 168 more
```

This PR fixes the problem by converting both these fields to ints from float64s before they are written to the event.

@elasticmachine
Copy link
Collaborator

Pinging @elastic/stack-monitoring (Stack monitoring)

func Unmarshal(data []byte, v interface{}) error {
dec := json.NewDecoder(bytes.NewReader(data))
dec.UseNumber()
return dec.Decode(v)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we also need to run

func TransformNumbers(dict common.MapStr) {

on the output to convert the json.Number back to a basic type?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the stack modules in Metricbeat are meant for Stack Monitoring, the events they produce are meant to get indexed into Elasticsearch (directly via output.elasticsearch or indirectly via another output). Elasticsearch can support numbers as strings (which is what json.Number is) as long as they are mapped as a numeric type. For example:

PUT foo
{
  "mappings": {
    "properties": {
      "n": { "type": "integer" },
      "d": { "type": "date", "format": "epoch_millis"}
    }
  }
}

# 1571647285959 == Monday, October 21, 2019 8:41:25.959 AM
POST foo/_doc
{
  "n": "999",
  "d": "1571647285959"
}

# Should return no hits
POST foo/_search
{
  "query": {
    "range": {
      "d": {
        "lt": 1571647285900
      }
    }
  }
}

# Should return 1 hit
POST foo/_search
{
  "query": {
    "range": {
      "n": {
        "lt": 1000
      }
    }
  }
}

So I think, in the case of these stack modules, it's okay to keep the umarshalled numbers as quoted strings?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I decided to go a different way altogether with the solution here. See #14222 (comment).

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(Haven't looked at the new approach yet.) My only concern with leaving the json.Number values in the event is that conditions in processors probably won't work. For example the range condition only works on primitive values.

@ycombinator
Copy link
Contributor Author

Based on the comment in elastic/elasticsearch#48472 (comment), it looks like only date fields really need to be handled as special — i.e. they can't have float64 values. I'll update this PR to make this more surgical change in all stack metricsets that produce date fields in their events.

@ycombinator ycombinator changed the title [Metricbeat] For stack modules, use json.UseNumber when unmarshalling [Metricbeat] Convert millis-since-epoch timestamps in elasticsearch/ml_job metricset to ints Oct 25, 2019
Copy link
Contributor

@cachedout cachedout left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can't comment too much on the specific implementation but on the whole, this looks like a positive change.

@ycombinator
Copy link
Contributor Author

jenkins, test this

Copy link
Member

@andrewkroh andrewkroh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That should fix it. 👍

@ycombinator
Copy link
Contributor Author

Travis CI is green. Jenkins CI failures are unrelated. Merging...

ycombinator added a commit that referenced this pull request Oct 29, 2019
…earch/ml_job` metricset to ints (#14222) (#14293)

* [Metricbeat] Convert millis-since-epoch timestamps in `elasticsearch/ml_job` metricset to ints (#14222)

* Convert timestamp field to int from float64

* Reformatting comment to be less wide

* Fixing up comment

* Adding unit tests

* Adding CHANGELOG entry

* Fixing up CHANGELOG
ycombinator added a commit that referenced this pull request Oct 29, 2019
…earch/ml_job` metricset to ints (#14222) (#14294)

* [Metricbeat] Convert millis-since-epoch timestamps in `elasticsearch/ml_job` metricset to ints (#14222)

* Convert timestamp field to int from float64

* Reformatting comment to be less wide

* Fixing up comment

* Adding unit tests

* Adding CHANGELOG entry

* Fixing up CHANGELOG
ycombinator added a commit that referenced this pull request Oct 29, 2019
…earch/ml_job` metricset to ints (#14222) (#14295)

* [Metricbeat] Convert millis-since-epoch timestamps in `elasticsearch/ml_job` metricset to ints (#14222)

* Convert timestamp field to int from float64

* Reformatting comment to be less wide

* Fixing up comment

* Adding unit tests

* Adding CHANGELOG entry

* Fixing up CHANGELOG
@ycombinator ycombinator deleted the mb-stack-unmarshal branch December 25, 2019 11:09
jorgemarey pushed a commit to jorgemarey/beats that referenced this pull request Jun 8, 2020
…ml_job` metricset to ints (elastic#14222)

* Convert timestamp field to int from float64

* Reformatting comment to be less wide

* Fixing up comment

* Adding unit tests

* Adding CHANGELOG entry
leweafan pushed a commit to leweafan/beats that referenced this pull request Apr 28, 2023
…earch/ml_job` metricset to ints (elastic#14222) (elastic#14293)

* [Metricbeat] Convert millis-since-epoch timestamps in `elasticsearch/ml_job` metricset to ints (elastic#14222)

* Convert timestamp field to int from float64

* Reformatting comment to be less wide

* Fixing up comment

* Adding unit tests

* Adding CHANGELOG entry

* Fixing up CHANGELOG
leweafan pushed a commit to leweafan/beats that referenced this pull request Apr 28, 2023
…earch/ml_job` metricset to ints (elastic#14222) (elastic#14294)

* [Metricbeat] Convert millis-since-epoch timestamps in `elasticsearch/ml_job` metricset to ints (elastic#14222)

* Convert timestamp field to int from float64

* Reformatting comment to be less wide

* Fixing up comment

* Adding unit tests

* Adding CHANGELOG entry

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

Successfully merging this pull request may close these issues.

Metricbeat stack modules may unmarshal large numbers into values Elasticsearch cannot understand
5 participants