optimize numerous things within the request that is specific to metrics.
(req *FetchSpansRequest)
| 1138 | |
| 1139 | // optimize numerous things within the request that is specific to metrics. |
| 1140 | func optimize(req *FetchSpansRequest) { |
| 1141 | if !req.AllConditions || req.SecondPassSelectAll { |
| 1142 | return |
| 1143 | } |
| 1144 | |
| 1145 | // Unscoped attributes like .foo require the second pass to evaluate |
| 1146 | for _, c := range req.Conditions { |
| 1147 | if c.Attribute.Scope == AttributeScopeNone && c.Attribute.Intrinsic == IntrinsicNone { |
| 1148 | // Unscoped (non-intrinsic) attribute |
| 1149 | return |
| 1150 | } |
| 1151 | } |
| 1152 | |
| 1153 | // There is an issue where multiple conditions &&'ed on the same |
| 1154 | // attribute can look like AllConditions==true, but are implemented |
| 1155 | // in the storage layer like ||'ed and require the second pass callback (engine). |
| 1156 | // TODO(mdisibio) - This would be a big performance improvement if we can fix the storage layer |
| 1157 | // Example: |
| 1158 | // { span.http.status_code >= 500 && span.http.status_code < 600 } | rate() by (span.http.status_code) |
| 1159 | exists := make(map[Attribute]struct{}, len(req.Conditions)) |
| 1160 | for _, c := range req.Conditions { |
| 1161 | if _, ok := exists[c.Attribute]; ok { |
| 1162 | // Don't optimize |
| 1163 | return |
| 1164 | } |
| 1165 | exists[c.Attribute] = struct{}{} |
| 1166 | } |
| 1167 | |
| 1168 | // Special optimization for queries like: |
| 1169 | // {} | rate() |
| 1170 | // {} | rate() by (rootName) |
| 1171 | // {} | rate() by (resource.service.name) |
| 1172 | // When the second pass consists only of intrinsics, then it's possible to |
| 1173 | // move them to the first pass and increase performance. It avoids the second pass/bridge |
| 1174 | // layer and doesn't alter the correctness of the query. |
| 1175 | // This can't be done for plain attributes or in all cases. |
| 1176 | if len(req.SecondPassConditions) > 0 { |
| 1177 | if !allIntrinsics(req.SecondPassConditions) { |
| 1178 | // Cannot move them. |
| 1179 | return |
| 1180 | } |
| 1181 | |
| 1182 | // Move all to first pass |
| 1183 | req.Conditions = append(req.Conditions, req.SecondPassConditions...) |
| 1184 | req.SecondPassConditions = nil |
| 1185 | } |
| 1186 | |
| 1187 | // If the remaining first layer is a single condition, then we can |
| 1188 | // eliminate the callback. |
| 1189 | if len(req.Conditions) == 1 { |
| 1190 | req.SecondPass = nil |
| 1191 | return |
| 1192 | } |
| 1193 | |
| 1194 | // Finally if the entire remaining first layer is intrinsics, then we can |
| 1195 | // elmininate the callback. |
| 1196 | // TODO(mdisibio): We can't eliminate the callback if other conditions exist, despite AllConditions, because the storage layer |
| 1197 | // doesn't strictly honor AllConditions for multiple attributes of the same type in the shared columns. |